Десериализация JSON с использованием JSon.NET с динамическими данными
Я пытаюсь десериализовать некоторые данные JSON в объекты для приложения. До сих пор это было прекрасно, потому что свойства данных JSON были статическими (ключ со значением). Теперь у меня есть результат, когда ключ является динамической частью данных.
Здесь пример JSON url:
http://en.wikipedia.org/w/api.php?action=query&format=json&pageids=6695&prop=info
В результате JSON для этого:
{ "query" : { "pages" : { "6695" : { "counter" : "",
"lastrevid" : 468683764,
"length" : 8899,
"ns" : 0,
"pageid" : 6695,
"title" : "Citadel",
"touched" : "2012-01-03T19:16:16Z"
} } } }
Хорошо, это замечательно, за исключением того, что я не могу десериализовать данные "страниц" в объекте. Если бы я определил класс для страниц, он должен был бы выглядеть так:
public class 6695
{
public string counter { get; set; }
public int lastrevid { get; set; }
public int length { get; set; }
public int ns { get; set; }
public int pageid { get; set; }
public string title { get; set; }
public string touched { get; set; }
}
Чтобы десеризовать содержимое (используя JsonConvert.Deserialize(jsondata)), и все мы знаем, что мы не можем иметь класс с именем 6695. Кроме того, имя класса должно быть другим (например, pageid = 7145 должен быть классом 7145).
Похоже, что я могу вырвать некоторые значения, если я использую что-то вроде JObject.Parse(content), а затем получаю доступ к элементам как JArrays, но это довольно уродливо, и я все еще пытаюсь вытащить данные из массива страниц.
Ищем кого-то, чтобы помочь с этим. Я не думаю, что это необычно, это просто не данные JSON, с которыми я сталкивался раньше, и не знаю, как с этим справиться.
Спасибо!
PS забыл упомянуть об этом на Windows Phone 7, поэтому "динамический" недоступен!
Ответы
Ответ 1
Вот как вы используете https://github.com/facebook-csharp-sdk/simple-json (https://nuget.org/packages/SimpleJson).
var text = "{\"query\":{\"pages\":{\"6695\":{\"pageid\":6695,\"ns\":0,\"title\":\"Citadel\",\"touched\":\"2012-01-03T19:16:16Z\",\"lastrevid\":468683764,\"counter\":\"\",\"length\":8899}}}}";
(Использование динамического)
dynamic json = SimpleJson.DeserializeObject(text);
string title = json.query.pages["6695"].title;
foreach (KeyValuePair<string, dynamic> page in json.query.pages)
{
var id = page.Key;
var pageId = page.Value.pageid;
var ns = page.Value.ns;
}
(Использование строго типизированных классов)
class result
{
public query query { get; set; }
}
class query
{
public IDictionary<string, page> pages { get; set; }
}
class page
{
public long pageid { get; set; }
public string title { get; set; }
}
var result = SimpleJson.DeserializeObject<result>(text);
[Обновление]
на телефоне Windows, где динамическая поддержка не поддерживается, и вы не хотите использовать строго типизированные классы.
var json = (IDictionary<string, object>)SimpleJson.DeserializeObject(text);
var query = (IDictionary<string, object>)json["query"];
var pages = (IDictionary<string, object>)query["pages"];
var pageKeys = pages.Keys;
var page = (IDictionary<string, object>)pages["6695"];
var title = (string)page["title"];
Ответ 2
Самый простой метод. В этом конкретном случае, вероятно, будет идти dynamic
.
dynamic data = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(json);
var lastRevId = data.query.pages["6695"].lastrevid;
Вы можете ссылаться на любой элемент с помощью этого имени []
, чтобы вы могли сделать что-то вроде data["query"]["pages"]["6695"]["lastrevid"]
. Это получит все те маленькие объекты, где имя недействительно в С#.
Ответ 3
Используя Json.net, вы можете просто сделать:
Dictionary<string,object> result = JsonConvert.DeserializeObject<Dictionary<string,object>>(json);
foreach(var item in result)
Console.WriteLine(item.Key + " " + item.Value);
Ответ 4
Надеюсь, что приведенный ниже пример поможет.
Я всегда разрабатываю модель, которая соответствует json. Гораздо лучше работать с объектом, когда это ваш собственный дизайн модели.
Очень легко сгенерировать модель С# из json. Я использую этот сайт для создания модели: http://json2csharp.com
Полный пример:
Код С#:
var targetsObject = Newtonsoft.Json.JsonConvert.DeserializeObject<YourModel>(jsonString);
JSON:
{
"investors": [
{
"name": "06",
"programs": [
{
"name": "Conventional",
"value": "3.5"
},
{
"name": "FHA - Standard",
"value": "5.0"
},
{
"name": "FHA - Streamline",
"value": ""
},
{
"name": "VA",
"value": "5.5"
},
{
"name": "VA IRRRL",
"value": "6.0"
},
{
"name": "Non-Prime",
"value": ""
}
]
},
{
"name": "07",
"programs": [
{
"name": "Conventional",
"value": "3.5"
},
{
"name": "FHA - Standard",
"value": "5.0"
},
{
"name": "FHA - Streamline",
"value": "7.0"
},
{
"name": "VA",
"value": "5.5"
},
{
"name": "VA IRRRL",
"value": ""
},
{
"name": "Non-Prime",
"value": ""
}
]
},
{
"name": "08",
"programs": [
{
"name": "Conventional",
"value": "3.5"
},
{
"name": "FHA - Standard",
"value": "5.0"
},
{
"name": "FHA - Streamline",
"value": "7.0"
},
{
"name": "VA",
"value": "5.5"
},
{
"name": "VA IRRRL",
"value": ""
},
{
"name": "Non-Prime",
"value": ""
}
]
},
{
"name": "09",
"programs": [
{
"name": "Conventional",
"value": "3.5"
},
{
"name": "FHA - Standard",
"value": "5.0"
},
{
"name": "FHA - Streamline",
"value": ""
},
{
"name": "VA",
"value": "5.5"
},
{
"name": "VA IRRRL",
"value": ""
},
{
"name": "Non-Prime",
"value": ""
}
]
},
{
"name": "10",
"programs": [
{
"name": "Conventional",
"value": ""
},
{
"name": "FHA - Standard",
"value": ""
},
{
"name": "FHA - Streamline",
"value": ""
},
{
"name": "VA",
"value": ""
},
{
"name": "VA IRRRL",
"value": ""
},
{
"name": "Non-Prime",
"value": "2.0"
}
]
},
{
"name": "11",
"programs": [
{
"name": "Conventional",
"value": "3.5"
},
{
"name": "FHA - Standard",
"value": "5.0"
},
{
"name": "FHA - Streamline",
"value": ""
},
{
"name": "VA",
"value": "6.0"
},
{
"name": "VA IRRRL",
"value": "6.0"
},
{
"name": "Non-Prime",
"value": ""
}
]
},
{
"name": "12",
"programs": [
{
"name": "Conventional",
"value": "3.5"
},
{
"name": "FHA - Standard",
"value": "5.0"
},
{
"name": "FHA - Streamline",
"value": ""
},
{
"name": "VA",
"value": "5.5"
},
{
"name": "VA IRRRL",
"value": "6.0"
},
{
"name": "Non-Prime",
"value": ""
}
]
},
{
"name": "13",
"programs": [
{
"name": "Conventional",
"value": ""
},
{
"name": "FHA - Standard",
"value": "5.0"
},
{
"name": "FHA - Streamline",
"value": ""
},
{
"name": "VA",
"value": ""
},
{
"name": "VA IRRRL",
"value": ""
},
{
"name": "Non-Prime",
"value": "2.0"
}
]
}
]
}
Модель:
public class Program
{
public string name { get; set; }
public string value { get; set; }
}
public class Investor
{
public string name { get; set; }
public List<Program> programs { get; set; }
}
public class RootObject
{
public List<Investor> investors { get; set; }
}
Ответ 5
Как насчет простого поиска и замены в строке JSON? Хотя это может быть не самое элегантное решение, возможно, это будет самый прагматичный.
Ответ 6
Возможно, вы могли бы просто использовать один зарезервированный атрибут для хранения типа объекта, а затем использовать базовый тип, как показано в этой статье: Динамические типы с JSON.NET