Есть ли в C # библиотека для разбора многоуровневого каскадного JSON? - PullRequest
10 голосов
/ 23 октября 2010

Есть ли библиотека (предпочтительно C #) для разрешения того, что я бы назвал многоуровневым каскадным JSON?

Вот пример того, что я имею в виду: (псевдокод / ​​C #)

var json1 = @"{
    ""firstName"": ""John"",
    ""lastName"": ""Smith""
    }";

var json2 = @"{
    ""firstName"": ""Albert""
    }";

var json3 = @"{
    ""phone"": ""12345""
    }";

var cascadingJSON = JSON.Cascade(json1, json2, json3);

Результат (Такое же поведение, как у CSS)

{
    "firstName"": "Albert", /*Overridden*/
    "lastName"": "Smith", /*Inherited*/
    "phone"": "12345"   }"; /*Added*/
}

Редактировать 1 - Более сложный пример

const string json1 =
                @"{
                     ""firstName"": ""John"",
                     ""lastName"": ""Smith"",
                     ""age"": 25,
                     ""address"": 
                     {
                         ""streetAddress"": ""21 2nd Street"",
                         ""city"": ""New York"",
                         ""state"": ""NY"",
                         ""postalCode"": ""10021""
                     },
                     ""phoneNumber"": 
                     [
                         {
                           ""type"": ""home"",
                           ""number"": ""212 555-1234""
                         },
                         {
                           ""type"": ""fax"",
                           ""number"": ""646 555-4567""
                         }
                     ]
                 }";

            const string json2 =
                @"{
                     ""firstName"": ""John2"",
                     ""lastName"": ""robert"",
                     ""age"": 25,
                     ""address"": 
                     {
                         ""state"": ""FL"",
                     },
                     ""phoneNumber"": 
                     [
                         {
                           ""type"": ""fax"",
                           ""number"": ""222 222-2222""
                         },
                         {
                           ""type"": ""iphone"",
                           ""number"": ""111 111-1111""
                         }
                     ]
                 }";

            const string json3 =
                @"{
                     ""firstName"": ""John3"",
                     ""father"": ""guy""
                 }";

            const string expectedResult =
                @"{
                     ""firstName"": ""John3"",
                     ""lastName"": ""robert"",
                     ""age"": 25,
                     ""father"": ""guy"",
                     ""address"": 
                     {
                         ""streetAddress"": ""21 2nd Street"",
                         ""city"": ""New York"",
                         ""state"": ""FL"",
                         ""postalCode"": ""10021""
                     },
                     ""phoneNumber"": 
                     [
                         {
                           ""type"": ""home"",
                           ""number"": ""212 555-1234""
                         },
                         {
                           ""type"": ""fax"",
                           ""number"": ""222 222-2222""
                         },
                         {
                           ""type"": ""iphone"",
                           ""number"": ""111 111-1111""
                         }
                     ]
                 }";

Редактировать 2

Подумав немного больше о требованиях, я вижу, что более сложный пример никогда не сможет работать как есть. Функция каскадирования не сможет узнать, был ли, например, определенный номер телефона изменен или он новый. Чтобы это работало, у каждого подобъекта должен быть уникальный идентификатор.

Ответы [ 2 ]

18 голосов
/ 23 октября 2010

Это очень легко, используя превосходную библиотеку JSON.NET .Этот метод объединяет объекты со свойствами, которые являются строками, числами или объектами.

public static string Cascade(params string[] jsonArray)
{
    JObject result = new JObject();
    foreach (string json in jsonArray)
    {
        JObject parsed = JObject.Parse(json);
        foreach (var property in parsed)
            result[property.Key] = property.Value;
    }
    return result.ToString();
}

Результат, приведенный в вашем примере:

{
  "firstName": "Albert",
  "lastName": "Smith",
  "phone": "12345"
}

Изменить в ответ на ваш обновленный вопрос:

Путем настройки рекурсивной работы этого решения вы можете объединять дочерние объекты.Следующий пример будет соответствовать вашим ожидаемым результатам (за исключением массива).Вы сможете легко расширить это решение для объединения массивов (JArray) аналогично тому, как оно объединяет объекты (JObject).

public static string Cascade(params string[] jsonArray)
{
    JObject result = new JObject();
    foreach (string json in jsonArray)
    {
        JObject parsed = JObject.Parse(json);
        Merge(result, parsed);
    }
    return result.ToString();
}

private static void Merge(JObject receiver, JObject donor)
{
    foreach (var property in donor)
    {
        JObject receiverValue = receiver[property.Key] as JObject;
        JObject donorValue = property.Value as JObject;
        if (receiverValue != null && donorValue != null)
            Merge(receiverValue, donorValue);
        else
            receiver[property.Key] = property.Value;
    }
}
2 голосов
/ 23 октября 2010

Не то, что я знаю. Для простого случая вы можете использовать любую библиотеку JSON, а затем объединить словари с решением, подобным this . Например. используя Newtonsoft / Json.NET:

Dictionary<String, String> dict1, dict2, dict3, merged;
dict1 = JsonConvert.DeserializeObject<Dictionary<string,string>>(json1);
dict2 = JsonConvert.DeserializeObject<Dictionary<string,string>>(json2);
dict3 = JsonConvert.DeserializeObject<Dictionary<string,string>>(json3);
merged = Merge(new[]{dict1, dict2, dict3});

Очевидно, что в рабочем коде вы должны выделить лишние строки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...