Dominique
Dominique

Reputation: 17543

How to add a (possibly empty) JSON property, based on a condition?

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?

Upvotes: 0

Views: 1412

Answers (2)

Laurent
Laurent

Reputation: 508

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

Upvotes: 2

derpirscher
derpirscher

Reputation: 17400

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

Upvotes: 1

Related Questions