【问题标题】:Deserialize part of JSON object and serialize it back with the remaining properties intact反序列化部分 JSON 对象并将其序列化回来,其余属性保持不变
【发布时间】:2014-11-14 19:39:40
【问题描述】:

我有一些 JSON 想要反序列化为 C# 类的实例。但是,该类没有与原始 JSON 匹配的所有字段/属性。我希望能够修改类中的属性值,然后将其序列化回 JSON,原始 JSON 中的剩余字段和属性仍然完好无损。

例如,假设我有以下 JSON:

{
    "name": "david",
    "age": 100,
    "sex": "M",
    "address": "far far away"
}

我想将它反序列化到这个类中:

class MyClass 
{  
    public string name { get; set; }  
    public int age { get; set; }  
}

反序列化后,我设置如下:

myClass.name = "John";
myClass.age = 200;

现在,我想将它序列化回 JSON 并得到这个结果:

{
    "name": "John",
    "age": 200,
    "sex": "M",
    "address": "far far away"
}

有没有办法使用 Json.Net 做到这一点?

【问题讨论】:

  • 这不是您想要的,但这至少是一种解决方案,stackoverflow.com/questions/1207731/…
  • 为什么不直接将属性添加到类中?
  • @MikkoViitala 他可能不知道其他属性是什么,或者它们的名称和数量可能是可变的。
  • @BrianRogers 是正确的。实际上 JSON 非常庞大,只想在强类型环境中修改一些字段,而不必定义所有字段。我确实想出了一个解决方案,我将在几秒钟内将其发布在这里

标签: c# json.net


【解决方案1】:

您可以使用 Json.Net 的“扩展数据”功能来处理此问题。

向您的类添加一个新的Dictionary<string, object> 属性并用[JsonExtensionData] 属性对其进行标记。 (如果您不想影响类的公共接口,可以将其设为私有属性。)在反序列化时,该字典将填充与您的类的任何其他公共属性不匹配的任何数据。在序列化时,字典中的数据将作为对象的属性写回 JSON。

class MyClass
{
    public string name { get; set; }
    public int age { get; set; }

    [JsonExtensionData]
    private Dictionary<string, object> otherStuff { get; set; }
}

这是一个演示:

class Program
{
    static void Main(string[] args)
    {
        string json = @"
        {  
            ""name"": ""david"",
            ""age"": 100,
            ""sex"": ""M"",
            ""address"": ""far far away""
        }";

        MyClass obj = JsonConvert.DeserializeObject<MyClass>(json);

        Console.WriteLine("orig name: " + obj.name);
        Console.WriteLine("orig age: " + obj.age);
        Console.WriteLine();

        obj.name = "john";
        obj.age = 200;

        json = JsonConvert.SerializeObject(obj, Formatting.Indented);
        Console.WriteLine(json);
    }
}

输出:

orig name: david
orig age: 100

{
  "name": "john",
  "age": 200,
  "sex": "M",
  "address": "far far away"
}

【讨论】:

    【解决方案2】:

    好的,所以在发布问题后,去吃午饭,回来我找到了解决方案。我没有使用 JSON.nets “扩展数据”,而是发现它们具有“合并”功能 http://james.newtonking.com/archive/2014/08/04/json-net-6-0-release-4-json-merge-dependency-injection

    IMO 我认为这更清洁,并决定采用这种方法。

    下面是我写的示例

    public class Cell
    {
      public string Text { get; set; }
      public int ID { get; set; }
      public CellStyle Style { get; set; }
    }
    
    public class CellStyle
    {
      public string BgColor { get; set; }
      public string TextColor { get; set; }
    }
    
    string json = @"{
      'Text': 'My Cell',
      'ID': 20,
      'TsID': 100,
      'Style':  {
                  'BgColor' : 'Red',
                  'TextColor' : 'Black',
                  'Caption' : 'Help My Cell',
                }
    }";
    
    var orgCell = JsonConvert.DeserializeObject<Cell>(json);
    orgCell.Style.TextColor = "White";
    orgCell.Style.BgColor = "Blue";
    
    var obj = JsonConvert.SerializeObject(orgCell);
    
    JObject o1 = JObject.Parse(json);
    JObject o2 = JObject.Parse(obj);
    
    o1.Merge(o2, new JsonMergeSettings
    {
      // union array values together to avoid duplicates
      MergeArrayHandling = MergeArrayHandling.Union
    });
    
    o1.ToString(); // gives me the intended string 
    

    【讨论】:

    • 不知道为什么你认为这个更清洁。除了更加复杂之外,从性能的角度来看,您还要进行两次额外的解析和一次合并。
    • 我实际上还不确定要使用哪种方法。我有顾虑,因为 JSON 本身有多个嵌套层,并且没有完全测试过任何一个 wyas。但至少我现在有解决方案的选择
    猜你喜欢
    • 2017-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-05
    • 2019-02-26
    • 1970-01-01
    • 2014-08-22
    相关资源
    最近更新 更多