Объединить две структуры JSON в одну в C # - PullRequest
0 голосов
/ 07 января 2019

У нас есть две похожие, но немного отличающиеся структуры JSON. Первая структура JSON предназначена для сценария без страт - это применимо для 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 - Multi Strata

{
    "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 сериализует JObject не игнорирует нули, даже с правильными настройками

Ответы [ 2 ]

0 голосов
/ 07 января 2019

Если ваши исходные результаты измерений No Strata и multi strata фактически уже сериализованы как структуры 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();

В качестве альтернативы, если ваши результаты JSON хранятся в некоторой коллекции файлов, вы можете объединить файлы непосредственно следующим образом:

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

Демонстрационная скрипка с юнит-тестами здесь .

Обновление

Если у вас есть множество объектов и вы хотите создать объединенный файл JSON путем объединения их представлений JSON, вы можете проецировать каждый объект в JObject, используя 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 здесь .

0 голосов
/ 07 января 2019

Вы можете просто сделать объединение (без создания сложных классов POCO, если вам это действительно не нужно). Newtonsoft поддерживает объединение JSon's:

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"
          }
        ]
      }
    }
  ]
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...