【问题标题】:How to add property in existing json using System.Text.Json library?如何使用 System.Text.Json 库在现有 json 中添加属性?
【发布时间】:2019-10-09 10:51:57
【问题描述】:
       {
          "TestData":{
              "Year__of__Account":"2019",
              "Tax___x0025_":"0.06",
              "Buildings__1":"1000",
              "Contents__1":"400",
              "Total_Insurable_Value":"100",
              "Buildings__Prem":"2560.8",
              "Contents__Prem":"1707.2",
              "YB__1":"1950",
              "No__Buildings":"55",
              "Location_Sprinklers_YN":"No",
              "test":"test"
           }
        }

在上面的示例 JSON 中,我想在属性“TestData”中添加一个名为“Name”的属性,其值为“John”。如何使用 .net Core 3.0 System.Text.Json 库来实现这一点。

我曾尝试使用 Utf8JsonWriter 的方法,但它正在创建一个新的 JSON 对象,而不是将其附加到上述现有 JSON 中。

        using (MemoryStream memoryStream1 = new MemoryStream())
        {
            using (Utf8JsonWriter utf8JsonWriter1 = new Utf8JsonWriter(memoryStream1))
            {
                using (JsonDocument jsonDocument = JsonDocument.Parse(json))
                {
                    utf8JsonWriter1.WriteStartObject();
                    utf8JsonWriter1.WritePropertyName("Name");
                    utf8JsonWriter1.WriteStringValue("John");
                    utf8JsonWriter1.WriteEndObject();

                    // how can I add above properties to JsonDocument object??
                }
            }
        }

【问题讨论】:

  • 我个人还没有开始安装 VS2019/Core3,所以我自己没有这样做,但大概你会使用 JsonDocument.Parse() 加载文档,就像你一样,添加新属性,然后用JsonDocument.WriteTo()写出来。
  • 是的,正是我的问题是如何在加载 JsonDocument 后添加新属性?我在他们的文档中找不到任何方法。
  • JsonDocument 是只读的。有一个未解决的问题Writable Json DOM #39922 跟踪此问题。相关但不重复:Modifying a JSON file using System.Text.Json.
  • 你能解决这个问题吗?我在指定位置插入属性时遇到问题,所以想知道您是否可以通过以下question 提供帮助。我可以同时使用 Newtonsoft 或 System.Text.Json。
  • 您无法使用 System.Text.Json 添加属性。使用 Newtonsoft JObject 将属性添加到您的 Json 对象。参考这个->JObject

标签: c# json .net-core-3.0 system.text.json


【解决方案1】:

假设可能有多个属性,并且您只想为“TestData”属性添加名称:

using (MemoryStream memoryStream1 = new MemoryStream())
{
    using (Utf8JsonWriter utf8JsonWriter1 = new Utf8JsonWriter(memoryStream1))
    {
        using (JsonDocument jsonDocument = JsonDocument.Parse(json))
        {
            utf8JsonWriter1.WriteStartObject();

            foreach (var element in jsonDocument.RootElement.EnumerateObject())
            {
                if (element.Name == "TestData")
                {
                    utf8JsonWriter1.WritePropertyName(element.Name);

                    // Staring new object
                    utf8JsonWriter1.WriteStartObject();

                    // Adding "Name" property 
                    utf8JsonWriter1.WritePropertyName("Name");
                    utf8JsonWriter1.WriteStringValue("John");

                    // Copying existing values from "TestData" object
                    foreach (var testDataElement in element.Value.EnumerateObject())
                    {
                        testDataElement.WriteTo(utf8JsonWriter1);
                    }

                    utf8JsonWriter1.WriteEndObject();
                }
                else
                {
                    element.WriteTo(utf8JsonWriter1);
                }
            }

            utf8JsonWriter1.WriteEndObject();
        }
    }

    var resultJson = Encoding.UTF8.GetString(memoryStream1.ToArray());
}

这里对于每个属性(“TestData”属性除外)我按原样写入整个值(通过调用element.WriteTo(utf8JsonWriter1)),对于“TestData”属性我开始一个新对象,添加“Name”属性然后复制每个“TestData”对象的属性。

附:这可行,但我很确定应该存在更好的解决方案。

【讨论】:

  • “我很确定应该存在更好的解决方案。”正是
  • 这是一种解决方法,因为您正在从现有的 JSON 对象创建新的 JSON 对象。但也许这是解决我的问题的唯一方法,因为 System.Text.Json 库中没有可用于 JSON 对象操作的方法。
【解决方案2】:

这是一个可能的答案

static void Main(string[] args)
    {
        var jsonString = @"
        {
            ""TestData"":{
                ""Year__of__Account"":""2019"",
                ""Tax___x0025_"":""0.06"",
                ""Buildings__1"":""1000"",
                ""Contents__1"":""400"",
                ""Total_Insurable_Value"":""100"",
                ""Buildings__Prem"":""2560.8"",
                ""Contents__Prem"":""1707.2"",
                ""YB__1"":""1950"",
                ""No__Buildings"":""55"",
                ""Location_Sprinklers_YN"":""No"",
                ""test"":""test""
            }
        }
        ";

        var jsonDoc = JsonSerializer.Deserialize<Dictionary<string, object>>(jsonString);

        var testDataDict = JsonSerializer.Deserialize<Dictionary<string, object>>(jsonDoc["TestData"].ToString());

        testDataDict.Add("Name", "John");

        //replace the test data with the modified test data
        jsonDoc["TestData"] = testDataDict;

        Console.WriteLine(JsonSerializer.Serialize(jsonDoc));
    }

【讨论】:

    【解决方案3】:

    我刚刚创建了一个 NuGet 包,其中包含一些希望对 JsonElement 有用的扩展方法,这些方法允许添加和/或删除属性。它基于使用 Utf8JsonWriter 在原始的基础上创建一个新的变异 JsonElement,如上面的答案。

    GitHub repo | NuGet package

    var jsonString = "{ \"Name\": \"Andrew\", \"EmailAddress\": \"a@b.com\" }";
    var jElement = JsonDocument.Parse(jsonString).RootElement;
    
    jElement = jElementAddProperty("Age", 38)
    .AddProperty("Male", true)
    .AddProperty("Female", false)
    .AddNullProperty("Alien")
    .AddProperty("Roles", new string[] { "admin", "user" })
    .AddProperty("LastUpdated", DateTime.UtcNow)
    .AddProperty("crazyNewObject", new
    {
        Name = "Hobbies",
        Value = "bass guitar and writing c# code"
    });
    

    希望有人会发现它们有用,但如果它们不能完全满足您的需求,请增强并提交拉取请求。

    【讨论】:

      【解决方案4】:

      使用JsonSerializer反序列化成嵌套字典也是可以的:

      static void Main(string[] args)
      {
          string testJson = @"
          {
          ""TestData"":{
              ""Year__of__Account"":""2019"",
              ""Tax___x0025_"":""0.06"",
              ""Buildings__1"":""1000"",
              ""Contents__1"":""400"",
              ""Total_Insurable_Value"":""100"",
              ""Buildings__Prem"":""2560.8"",
              ""Contents__Prem"":""1707.2"",
              ""YB__1"":""1950"",
              ""No__Buildings"":""55"",
              ""Location_Sprinklers_YN"":""No"",
              ""test"":""test""
              }
          }";
      
          using (var memoryStream1 = new MemoryStream())
          {
              using (var utf8JsonWriter1 = new Utf8JsonWriter(memoryStream1))
              {
                  //For each level in json tree an additional dictionary must be added
                  var jsonDict = JsonSerializer.Deserialize<Dictionary<string, Dictionary<string, object>>>(testJson);
                  jsonDict["TestData"].Add("Name", "John");
                  JsonSerializer.Serialize<object>(utf8JsonWriter1, jsonDict);
              }
      
              string testString = Encoding.UTF8.GetString(memoryStream1.ToArray());
          }
      }
      

      但请注意,新属性始终添加在 TestData 块的末尾。

      【讨论】:

        猜你喜欢
        • 2021-12-28
        • 2022-01-08
        • 2011-03-30
        • 1970-01-01
        • 2021-08-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-01-15
        相关资源
        最近更新 更多