代码之家  ›  专栏  ›  技术社区  ›  LCJ

在C中将两个JSON结构合并为一个#

  •  -2
  • LCJ  · 技术社区  · 7 年前

    JSON 1无地层

    {
        "testTIN": "123",
        "measurements": [{
                "measureId": "001",
                "value": {
                    "IsEndToEndReported": true,
                    "PerformanceMet": 5
                }
            },
            {
                "measureId": "002",
                "value": {
                    "IsEndToEndReported": true,
                    "PerformanceMet": 6
                }
    
            }
        ]
    }
    

    JSON 2多层

    {
        "testTIN": "123",
        "measurements": [
           {
            "measureId": "003",
            "value": {
                "strata": [{
                        "IsEndToEndReported": true,
                        "PerformanceMet": 5,
                        "Stratum": "Level1"
                    },
                    {
                        "IsEndToEndReported": true,
                        "PerformanceMet": 6,
                        "Stratum": "Level2"
                    }
                ]
            }
        }
       ]
    }
    

    预期的JSON

    {
        "testTIN": "123",
        "measurements": [{
                "measureId": "001",
                "value": {
                    "IsEndToEndReported": true,
                    "PerformanceMet": 5
                }
            },
            {
                "measureId": "002",
                "value": {
                    "IsEndToEndReported": true,
                    "PerformanceMet": 6
                }
            },
            {
                "measureId": "003",
                "value": {
                    "strata": [{
                            "IsEndToEndReported": true,
                            "PerformanceMet": 5,
                            "Stratum": "Level1"
                        },
                        {
                            "IsEndToEndReported": true,
                            "PerformanceMet": 6,
                            "Stratum": "Level2"
                        }
                    ]
                }
            }
        ]
    }
    

    如何将上述两种JSON结构结合起来,得到这种新的JSON结构?

    C#代码

    //No Strata
            List<FlattenedRawData> rowList_NoStrata = HelperMethodClasses.GetFlattenedRawData_NoStrata();
            List<MeasurementSet__NoStrata> result_NoStrata = rowList_NoStrata.GroupBy(records => records.EffectiveTIN)
                         .Select(y => new MeasurementSet__NoStrata
                         {
                             testTIN = y.Key,
                             measurements = y.Select(i =>
                                     new Measurement_NoStrata()
                                     {
                                         measureId = i.MeasureID,
                                         value = new QualityMeasureValue_NoStrata
                                         {
                                             IsEndToEndReported = true,
                                             PerformanceMet = i.PerformanceMetCount
                                         }
                                     })
                                .ToList()
                         })
                    .ToList();
    
            //Multi Strata
            List<FlattenedRawData> rowList_MultiStrata = HelperMethodClasses.GetFlattenedRawData_MultiStrata();
            List<MeasurementSet__MultiStrata> resul_MultiStrata =
                            rowList_MultiStrata.GroupBy(groupBy1 => groupBy1.EffectiveTIN)
                            .Select(level1 => new MeasurementSet__MultiStrata
                            {
                                testTIN = level1.Key,
                                measurements = level1.GroupBy(groupBy2 => groupBy2.MeasureID).Select(level2 =>
                                new Measurement_MultiStrata()
                                {
                                    measureId = level2.Key,
                                    value = new QualityMeasureValue_MultiStrata()
                                    {
                                        strata = level2.Select(level3 => new Strata
                                        {
                                            IsEndToEndReported = true,
                                            PerformanceMet = level3.PerformanceMetCount,
                                            Stratum = level3.Stratum 
                                        }).ToList(),
                                    }
                                }).ToList()
                            }).ToList();
    
    
            string requestJson = Newtonsoft.Json.JsonConvert.SerializeObject(resul_MultiStrata[0]);
    
    public class FlattenedRawData
    {
        public string EffectiveTIN { get; set; }
        public string MeasureID { get; set; }
        public int PerformanceMetCount { get; set; }
        public string Stratum { get; set; }
    }
    
    public class Measurement_NoStrata
    {
        public string measureId { get; set; }
        public QualityMeasureValue_NoStrata value { get; set; }
    }
    
    public class Measurement_MultiStrata
    {
        public string measureId { get; set; }
        public QualityMeasureValue_MultiStrata value { get; set; }
    }
    
    
    public class QualityMeasureValue_NoStrata
    {
        public bool IsEndToEndReported { get; set; }
        public int PerformanceMet { get; set; }
    }
    
    
    public class QualityMeasureValue_MultiStrata
    {
        public List<Strata> strata = new List<Strata>();
    }
    
    public class Strata
    {
        public bool IsEndToEndReported { get; set; }
        public int PerformanceMet { get; set; }
        public string Stratum { get; set; }
    }
    
    
    public class MeasurementSet__NoStrata
    {
        public string testTIN { get; set; }
        public List<Measurement_NoStrata> measurements { get; set; }
    }
    
    public class MeasurementSet__MultiStrata
    {
        public string category { get; set; }
        public string testTIN { get; set; }
        public List<Measurement_MultiStrata> measurements { get; set; }
    }
    

    使现代化

    1. Newtonsoft Json.Net serialize JObject doesn't ignore nulls, even with the right settings
    2 回复  |  直到 7 年前
        1
  •  4
  •   Gauravsa    7 年前

    你可以简单地做一个测试 union (除非您确实需要,否则无需创建复杂的POCO类)。Newtonsoft支持合并JSon:

    var dataObject1 = JObject.Parse(@"{
                ""testTIN"" : ""123"",
                ""measurements"": [{
                    ""measureId"": ""001"",
                    ""value"": {
                        ""IsEndToEndReported"": true,
                        ""PerformanceMet"": 5
                    }
                },
                {
                    ""measureId"": ""002"",
                    ""value"": {
                        ""IsEndToEndReported"": true,
                        ""PerformanceMet"": 6
                    }
                }
                ]
            }");
    
            var dataObject2 = JObject.Parse(@"{
            ""testTIN"": ""123"",
            ""measurements"": [
            {
                ""measureId"": ""003"",
                ""value"": {
                    ""strata"": [{
                        ""IsEndToEndReported"": true,
                        ""PerformanceMet"": 5,
                        ""Stratum"": ""Level1""
                    },
                    {
                        ""IsEndToEndReported"": true,
                        ""PerformanceMet"": 6,
                        ""Stratum"": ""Level2""
                    }
                    ]
                }
            }
            ]
            }");
    
            dataObject1.Merge(dataObject2, new JsonMergeSettings
            {
                // union array values together to avoid duplicates
                MergeArrayHandling = MergeArrayHandling.Union
            });
    
            string json = dataObject1.ToString();
    

    这将给出一个输出:

        {
      "testTIN": "123",
      "measurements": [
        {
          "measureId": "001",
          "value": {
            "IsEndToEndReported": true,
            "PerformanceMet": 5
          }
        },
        {
          "measureId": "002",
          "value": {
            "IsEndToEndReported": true,
            "PerformanceMet": 6
          }
        },
        {
          "measureId": "003",
          "value": {
            "strata": [
              {
                "IsEndToEndReported": true,
                "PerformanceMet": 5,
                "Stratum": "Level1"
              },
              {
                "IsEndToEndReported": true,
                "PerformanceMet": 6,
                "Stratum": "Level2"
              }
            ]
          }
        }
      ]
    }
    
        2
  •  2
  •   dbc    7 年前

    无地层 多层 事实上,测量结果已经序列化为 JSON结构 ,您可以使用 JContainer.Merge(Object, JsonMergeSettings) MergeArrayHandling.Concat

    // Get the initial measurement JSON measurements as strings.
    IEnumerable<string> measturements = GetJsonMeasurements();
    
    // And concatenate them together into a combined `JObject`:
    var settings = new JsonMergeSettings { MergeArrayHandling = MergeArrayHandling.Concat };
    var json = measturements.Aggregate(new JObject(),
                                       (j, s) => { j.Merge(JObject.Parse(s), settings); return j; });
    

    在这里,我假设测量值已经按照 "testTIN" JObject 并按 “testTIN” 聚合前的值,如下所示:

    var settings = new JsonMergeSettings { MergeArrayHandling = MergeArrayHandling.Concat };
    var json = measurements
        .Select(j => JObject.Parse(j))
        .GroupBy(j => (string)j["testTIN"])
        .Select(g => g.Aggregate(new JObject(),
                                 (j1, j2) => { j1.Merge(j2, settings); return j1; })
                )
        .ToList();
    

    var settings = new JsonMergeSettings { MergeArrayHandling = MergeArrayHandling.Concat };
    var json = fileNames.Aggregate(new JObject(),
                                   (j, s) => 
                                   { 
                                       using (var file = File.OpenText(s))
                                       using (var reader = new JsonTextReader(file))
                                       {
                                           j.Merge(JToken.Load(reader), settings);
                                       }
                                       return j; 
                                   });
    

    演示如何处理单元测试 here

    使现代化

    使用 JObject.FromObject

    // Get the results
    IEnumerable<MeasurementSet__NoStrata> measurements1 = GetNoStrataMeasurements(); // Get no-strata measurements.
    IEnumerable<MeasurementSet__MultiStrata> measurements2 = GetMultiStrataMeasurements(); // Get multistrata measurements.
    
    // Combine them into a single enumerable
    IEnumerable<object> measurements = measurements1.Cast<object>()
        .Concat(measurements2.Cast<object>());
    
    // Select serialization and merge settings
    var serializerSettings = new JsonSerializerSettings
    {
        // Put whatever you want here, e.g.
        NullValueHandling = NullValueHandling.Ignore,
    };
    var mergeSettings = new JsonMergeSettings 
    { 
        // Required
        MergeArrayHandling = MergeArrayHandling.Concat,
        // Put whatever you want here, either Ignore or Merge
        // https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_Linq_MergeNullValueHandling.htm
        MergeNullValueHandling = MergeNullValueHandling.Ignore, // Or Merge if you prefer
    };
    
    // Serialize and merge the results
    var serializer = JsonSerializer.CreateDefault(serializerSettings);
    var json = measurements
        .Select(m => JObject.FromObject(m, serializer))
        .GroupBy(j => (string)j["testTIN"])
        .Select(g => g.Aggregate(new JObject(),
                                 (j1, j2) => { j1.Merge(j2, mergeSettings); return j1; })
                )
        // Do we need to remove the `"category"` property?
        // If so do it here.
        .Select(o => { o.Remove("category"); return o; })
        .ToList();
    

    演示小提琴#2 here .