【问题标题】:How to add a (possibly empty) JSON property, based on a condition?如何根据条件添加(可能为空的)JSON 属性?
【发布时间】:2021-07-27 13:20:25
【问题描述】:

昨天,我需要在 JSON 文件中添加一个属性,我已使用 DefaultHandling 完成此操作,如 this previous question 中所述:

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

现在我正在处理一个更复杂的情况:

我的源代码摘录:

[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; }
...

所需的 JSON 结果:

"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 */
...

所以我的问题是,这是否可能(伪代码),如果是,如何?

[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; }

编辑(在Laurent第一次回答后)

我的序列化代码如下:

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

如果在属性声明中不能做,可以在这里做吗?

【问题讨论】:

标签: c# json serialization json.net


【解决方案1】:

您的属性中不能有条件,请尝试在常规代码中设置这些条件默认值。 (属性只能有常量值)

【讨论】:

【解决方案2】:

你可以使用json.net的Conditional Property Serialization

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;
  }

}

所以一个属性只有在ShouldSerialize[PropertyName]()返回true时才会被序列化;

另见this fiddle

编辑

是的,你的JsonSerializerSettings 中的DefaultValueHandling.Ignore 确实可能对序列化的结果有影响。即,即使ShouldSerialize... 返回true,如果一个属性等于默认值,它也不会被序列化(在这种特殊情况下,bool 永远不会被序列化,如果它是falseDefaultValueHandling.Ignore 是设置)。

因此,如果您总是想在 NAME 等于 i1 时序列化 i1ENABLE,则必须覆盖此属性的 DefaultValueHandling

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;
  }
}

所以当你如下序列化时

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

属性i1ENABLE总是被序列化,当NAME == "i1"从不被序列化NAME != "i1"

ShouldSerialize... 可能是最早的过滤器之一,它是在属性序列化期间完成的。如果它返回false,则永远不会序列化此属性。但如果它返回true,还有其他检查。其中之一是DefaultValueHandling。因此,如果 DefaultValueHandling 设置为 Ignore 一个布尔值 false 将不会被序列化,即使 ShouldSerialize... 返回 true。

另请参阅updated fiddle

【讨论】:

  • 谢谢,但它不起作用(虽然调用了函数ShouldSerialize...(),但我使用调试器检查了)。如我原始问题的编辑中所述,它是否与DefaultHandling 相关? (哦,我也验证了NAME == ...的结果,这也是正确的)
  • 咳咳,你复制了这个答案的代码吗?我刚刚看到方法名称中有错字。我写了ShouldSerialie... 而不是ShouldSerialize... 除此之外,不,它不应该与 DefaultHandling 或其他任何事情有关。如果ShouldSerialize... 返回 false,则该属性根本不应该被序列化
  • 是的,我看到了你的拼写错误,但是我使用的函数名称是正确的(否则它们不会被调试器捕获)。
  • 你能用调试器验证ShouldSerialize...确实返回了正确的值
  • 我有:在这种特殊情况下,返回值确实是true,而在其他情况下它是false。所以结果应该是正确的。如我的问题编辑中所述,问题是否可能是由基本的JsonSerializerSettings 引起的?
猜你喜欢
  • 2022-01-16
  • 2022-01-15
  • 1970-01-01
  • 1970-01-01
  • 2019-08-18
  • 2023-03-05
  • 2021-09-06
  • 2020-09-22
  • 1970-01-01
相关资源
最近更新 更多