【问题标题】:Is there a way to dynamically switch fields from a model in the JSON representation of an object?有没有办法在对象的 JSON 表示中从模型中动态切换字段?
【发布时间】:2021-08-12 20:56:07
【问题描述】:

我有一个对象的 JSON 表示形式以及下面列出的相关模型类。 MinionSettingsLeeSettings 这两个类是从基本抽象泛型类派生的类。

{
    "charSetting": {
        "minionSettings": {
            "key": "minionSettings",
            "value": [1,2,3]
        },
        "leeSettings": {
            "key": "leeSettings",
            "value": [
                {
                    "baseAD": 1,
                    "baseAP": 1,
                    "visible": true
                }
            ]
        }
    }
}
public class CharacterSettingsWrapper
{
    public CharacterSettings CharSetting { get; set; }
}

public class CharacterSettings 
{
    public MinionSettings MinionSettings { get; set; }

    public LeeSettings LeeSettings { get; set; }
}

[DataContract]
public class MinionSettings : CharacterSetting<List<int>>
{
    public MinionSettings()
    {
        Key = "minionSettings";
        Value = new List<int>();
    }
}

public class LeeSettings : CharacterSetting<List<LeeSetting>>
{
    public LeeSettings()
    {
        Key = "leeSettings";
        Value = new List<LeeSetting>();
    }
}

有什么方法可以保留 CharacterSettings 类中的所有字段,但将它们从对象的 JSON 表示中删除,同时保留相关的键/值对,所以我希望 JSON 如下所示。如果没有,我还能做些什么来实现这一目标?

我已经尝试使用我的基本抽象类,但由于它是抽象类,我无法创建它的实例,因此它不能很好地工作,并且这些数据是从 JSON 中提取的,然后放入相关对象中基于派生类(如MinionSettingsLeeSettings这两个类)

{
   "charSetting":[
      {
         "key":"minionSettings",
         "value":[
            1,
            12,
            3
         ]
      },
      {
         "key":"leeSettings",
         "value":[
            {
               "baseAD":1,
               "baseAP":1,
               "visible":true
            }
         ]
      }
   ]
}

【问题讨论】:

  • 为什么不删除Key。最终的 XML 会有些不同,但会消除重复。我看不到 Key 属性的用途,因为它是带有初始小写字母的类名。
  • 在您的目标 JSON 中,您希望您的反序列化如何识别 charSetting 数组的每个元素并实例化正确的类? JSON 中没有任何信息表明在哪里使用了哪种类型。
  • @Matt:OP 的目标 JSON 不仅有一个省略的属性,它还有一个明显不同的结构。
  • @Flater - 但是这个问题具有误导性。它要求在 JSON 表示中隐藏一个字段,这实际上与排除输出的属性相同。所以要么编辑问题的标题,要么描述文本应该与问题匹配。
  • @Matt:我猜 OP 说错了。初始/目标 JSON 之间的主要区别是缺少两个属性名称(但 不是 属性的值 - 这是您错过的部分)。在 OP 的辩护中,通过发布预期的输出示例和声明 “将它们从对象的 JSON 表示中删除 同时保留相关的键/值对,很容易暴露出措辞中的混淆。我确实同意 OP 明确提出的问题乍一看具有误导性,但问题中有足够的信息来理解 OP 的意图。

标签: c# json json.net


【解决方案1】:

您可以完全通过使用JObjectJArray 对象来解决这个问题,而无需创建和使用任何域对象。

在下面的代码中,我假设节点存在(以保持代码简单),但在生产代码中,请优先使用 TryGetValue (Ref) 而不是索引运算符 (Ref)。

//Retrieve the nodes from the original json
var json = File.ReadAllText("sample.json");
var root = JObject.Parse(json);
var charSetting = root["charSetting"];
var minionSettings = charSetting["minionSettings"];
var leeSettings = charSetting["leeSettings"];

//Construct the new json based on the retrieved values
var newcharSetting = new JArray();
newcharSetting.Add(minionSettings);
newcharSetting.Add(leeSettings);
var newRoot = new JObject();
newRoot.Add("charSetting", newcharSetting);
Console.WriteLine(newRoot.ToString());

我还必须提到,这段代码很大程度上依赖于示例 json 的结构。因此,它不足以处理与此类似的任何类型的结构。

打印的输出如下所示:

{
  "charSetting": [
    {
      "key": "minionSettings",
      "value": [
        1,
        2,
        3
      ]
    },
    {
      "key": "leeSettings",
      "value": [
        {
          "baseAD": 1,
          "baseAP": 1,
          "visible": true
        }
      ]
    }
  ]
}

【讨论】:

  • 读者注意:这确实会使 JSON 不可反序列化,因为反序列化程序不知道这些数组元素使用什么具体类型。
  • @Flater 我认为这同样适用于 OP 的请求。我的理解正确吗?
  • 是的。并不是要批评您的答案,而是要为想要使用此答案的读者准备的。
猜你喜欢
  • 2021-01-07
  • 2021-10-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-10
  • 2023-01-20
  • 2012-12-19
相关资源
最近更新 更多