0

Yesterday, I needed to add a property in a JSON file, I've done this using DefaultHandling, as mentioned in this previous question:

[JsonProperty("DIAGNOSTICS", DefaultValueHandling = DefaultValueHandling.Populate)]
public bool DIAGNOSTICS { get; set; }

Now I'm dealing with a more complicated situation:

Excerpt of my source code:

[JsonProperty("NAME")]
public string NAME { get; set; }
[JsonProperty("i1.ENABLE")]
public bool i1ENABLE { get; set; }
[JsonProperty("i2.ENABLE")]
public bool i2ENABLE { get; set; }
[JsonProperty("i3ENABLE")]
public bool i3ENABLE { get; set; }
...

Desired JSON result:

"NAME": "i1",
"i1.ENABLE": false, /* i2.ENABLE and i3.ENABLE are not shown */
...
"NAME": "i2",
"i2.ENABLE": false, /* i1.ENABLE and i3.ENABLE are not shown */
...
"NAME": "i3",
"i3.ENABLE": false, /* i1.ENABLE and i2.ENABLE are not shown */
...

So my question is, is this possible (pseudo-code) and in case yes, how?

[JsonProperty("i1.ENABLE", DefaultValueHandling = (IF(NAME=="i1") THEN DefaultValueHandling.Populate))]
public bool i1ENABLE { get; set; }
[JsonProperty("i2.ENABLE", DefaultValueHandling = (IF(NAME=="i2") THEN DefaultValueHandling.Populate))]
public bool i2ENABLE { get; set; }
[JsonProperty("i3.ENABLE", DefaultValueHandling = (IF(NAME=="i3") THEN DefaultValueHandling.Populate))]
public bool i3ENABLE { get; set; }

Edit (after first answer from Laurent)

My serialisation code is the following:

JsonSerializerSettings js = new JsonSerializerSettings();
js.DefaultValueHandling = DefaultValueHandling.Ignore;
string temp = JsonConvert.SerializeObject(root, Formatting.Indented, js);

In case it can't be done in the property declaration, can it be done here?

Dominique
  • 16,450
  • 15
  • 56
  • 112
  • Does this answer your question? [Serialize Property, but Do Not Deserialize Property in Json.Net](https://stackoverflow.com/questions/31731320/serialize-property-but-do-not-deserialize-property-in-json-net) – masoud Jul 27 '21 at 14:32
  • @masoud: that other question does not answer my question. – Dominique Jul 27 '21 at 14:35

2 Answers2

2

You cannot have conditions in your attributes, try setting these conditional default values in regular code instead. (Attributes can only have constant values)

Laurent
  • 478
  • 7
  • 15
1

You could make use of the Conditional Property Serialization of json.net

class CC {
  [JsonProperty("NAME")]
  public string NAME { get; set; }

  [JsonProperty("i1.ENABLE")]
  public bool i1ENABLE { get; set; }

  [JsonProperty("i2.ENABLE")]
  public bool i2ENABLE { get; set; }

  [JsonProperty("i3.ENABLE")]
  public bool i3ENABLE { get; set; }

  public bool ShouldSerializei1ENABLE() {
    bool r = NAME == "i1";
    return r;
  }

  public bool ShouldSerializei2ENABLE() {
    bool r = NAME == "i2";
    return r;
  }

  public bool ShouldSerializei3ENABLE() {
    bool r = NAME == "i3";
    return r;
  }

}

So a property will only be serialized if ShouldSerialize[PropertyName]() returns true;

See also this fiddle

EDIT

Yes, the DefaultValueHandling.Ignore in your JsonSerializerSettings may indeed have an influence on the result of the serialization. Ie, even if ShouldSerialize... returns true, a property won't be serialized if it equals to the default value (in this particular case a bool will never be serialized, if it's false and DefaultValueHandling.Ignore is set).

So, if you always want to serialize i1ENABLE when NAME equals i1, you have to override the DefaultValueHandling for this property.

class CC {
  [JsonProperty("NAME")]
  public string NAME { get; set; }

  [JsonProperty("i1.ENABLE", DefaultValueHandling=DefaultValueHandling.Populate)]
  public bool i1ENABLE { get; set; }

  public bool ShouldSerializei1ENABLE() {
    bool r = NAME == "i1";
    return r;
  }
}

So when you serialize as follows

JsonSerializerSettings js = new JsonSerializerSettings();
js.DefaultValueHandling = DefaultValueHandling.Ignore;
string temp = JsonConvert.SerializeObject(root, Formatting.Indented, js);

the property i1ENABLE will always be serialized, when NAME == "i1" but never be serialized when NAME != "i1"

ShouldSerialize... is probably one of the first filters, that is done during serialization of a property. If it returns false, this property is never serialized. But if it returns true, there are still other checks. One of them is DefaultValueHandling. So if DefaultValueHandling is set to Ignore a boolean with value false won't be serialized, even if ShouldSerialize... returns true.

Please see also this updated fiddle

derpirscher
  • 14,418
  • 3
  • 18
  • 35
  • Ahem, did you copy the code from this answer? I just saw there is a typo in the methods' name. I wrote `ShouldSerialie...` instead of `ShouldSerialize...` Other than that, no it should not have anything to do with DefaultHandling or anything other. If `ShouldSerialize...` returns false, the property should not be serialized at all – derpirscher Jul 27 '21 at 14:35
  • Yes, I have seen your spelling mistake, but the names of the functions I used were correct (otherwise they would not be catched by the debugger). – Dominique Jul 27 '21 at 14:37
  • Can you verify with the debugger, that `ShouldSerialize...` indeed returns the correct value – derpirscher Jul 27 '21 at 14:47
  • I have: the return value is indeed `true` in that particular case, and it is `false` for the other cases. So the result should be correct. Is it possible that the issue is caused by the basic `JsonSerializerSettings`, as mentioned in the edit of my question? – Dominique Jul 27 '21 at 14:49
  • Sorry, I misunderstood you. I thought a property was serialized, eventhough it shouldn't. But it's the other way around, the property is still missing, eventhough `ShouldSerialize` returns true. Please see the updatet answer – derpirscher Jul 27 '21 at 15:48