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

时间:2019-01-07 02:28:37

标签: c# json oop json.net

我们有两个相似但略有不同的JSON结构。第一个JSON结构适用于No Strata场景–适用于measureId“ 001”和“ 002”。第二个JSON结构用于多层次–适用于“ measureId”:“ 003”。对于每个testTIN,我们需要将这两个度量值结合起来,如预期的JSON结构所示。

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 个答案:

答案 0 :(得分:3)

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

Mat eye3 = Mat::eye(3, 3, CV_64F); 
cvUndistortPoints(src, dst, &camera1, &distCoeffs1, &eye3,&camera1);

这将给出输出:

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();

答案 1 :(得分:2)

实际上,如果您最初的 No Strata multi strata 测量结果已经序列化为 JSON结构,则可以简单地合并它们结合使用JContainer.Merge(Object, JsonMergeSettings)和合并设置MergeArrayHandling.Concat如下:

$ ls ~/.docker
config.json daemon.json machine

$ cat ~/.docker/config.json
{
  "auths" : {
    "unicareer.azurecr.io" : {

    },
    "https://unicareer.azurecr.io" : {

    }
  },
  "HttpHeaders" : {
    "User-Agent" : "Docker-Client/18.09.0 (darwin)"
  },
  "credSstore" : "osxkeychain",
  "stackOrchestrator" : "swarm",
  "credsStore" : "osxkeychain"
}

在这里,我假设测量值已经按// 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"

或者,如果您的JSON结果存储在某些文件集合中,则可以按如下所示直接从文件进行合并:

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();

使用单元测试here演示演示。

更新

如果您有大量对象,并且希望通过合并它们的JSON表示来创建组合的JSON文件,则可以使用JObject.FromObject将每个对象投影到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; }); ,然后合并这些对象:

JObject

演示小提琴#2 here