#c# #json #dynamic
#c# #json #динамический
Вопрос:
Я пытаюсь получить значение свойства из динамического объекта, указав имя свойства, это работает с использованием индекса, но мне нужно передать конкретное имя свойства, чтобы получить значение [поскольку имя будет сохранено в базе данных, а не в индексе]
var serializer = new JavaScriptSerializer();
serializer.RegisterConverters(new[] { new DynamicJsonConverter() });
dynamic data = serializer.Deserialize(jsonText, typeof(object));
data.Response.Outcome.KeyValueOfstringOutcomepQnxSKQu["PropertyName"]
Это код для преобразования моего jSON в динамический класс, для которого я пытаюсь получить значения из указанного свойства
public sealed class DynamicJsonConverter : JavaScriptConverter
{
public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
{
if (dictionary == null)
throw new ArgumentNullException("dictionary");
return type == typeof(object) ? new DynamicJsonObject(dictionary) : null;
}
public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
{
throw new NotImplementedException();
}
public override IEnumerable<Type> SupportedTypes
{
get { return new ReadOnlyCollection<Type>(new List<Type>(new[] { typeof(object) })); }
}
#region Nested type: DynamicJsonObject
private sealed class DynamicJsonObject : DynamicObject
{
private readonly IDictionary<string, object> _dictionary;
public DynamicJsonObject(IDictionary<string, object> dictionary)
{
if (dictionary == null)
throw new ArgumentNullException("dictionary");
_dictionary = dictionary;
}
public override string ToString()
{
var sb = new StringBuilder("{");
ToString(sb);
return sb.ToString();
}
private void ToString(StringBuilder sb)
{
var firstInDictionary = true;
foreach (var pair in _dictionary)
{
if (!firstInDictionary)
sb.Append(",");
firstInDictionary = false;
var value = pair.Value;
var name = pair.Key;
if (value is string)
{
sb.AppendFormat("{0}:"{1}"", name, value);
}
else if (value is IDictionary<string, object>)
{
new DynamicJsonObject((IDictionary<string, object>)value).ToString(sb);
}
else if (value is ArrayList)
{
sb.Append(name ":[");
var firstInArray = true;
foreach (var arrayValue in (ArrayList)value)
{
if (!firstInArray)
sb.Append(",");
firstInArray = false;
if (arrayValue is IDictionary<string, object>)
new DynamicJsonObject((IDictionary<string, object>)arrayValue).ToString(sb);
else if (arrayValue is string)
sb.AppendFormat(""{0}"", arrayValue);
else
sb.AppendFormat("{0}", arrayValue);
}
sb.Append("]");
}
else
{
sb.AppendFormat("{0}:{1}", name, value);
}
}
sb.Append("}");
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
if (!_dictionary.TryGetValue(binder.Name, out result))
{
// return null to avoid exception. caller can check for null this way...
result = null;
return true;
}
result = WrapResultObject(result);
return true;
}
public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
{
if (indexes.Length == 1 amp;amp; indexes[0] != null)
{
if (!_dictionary.TryGetValue(indexes[0].ToString(), out result))
{
// return null to avoid exception. caller can check for null this way...
result = null;
return true;
}
result = WrapResultObject(result);
return true;
}
return base.TryGetIndex(binder, indexes, out result);
}
private static object WrapResultObject(object result)
{
var dictionary = result as IDictionary<string, object>;
if (dictionary != null)
return new DynamicJsonObject(dictionary);
var arrayList = result as ArrayList;
if (arrayList != null amp;amp; arrayList.Count > 0)
{
return arrayList[0] is IDictionary<string, object>
? new List<object>(arrayList.Cast<IDictionary<string, object>>().Select(x => new DynamicJsonObject(x)))
: new List<object>(arrayList.Cast<object>());
}
return resu<
}
}
#endregion
}
Это Json
{
"Response": {
"Outcome": {
"KeyValueOfstringOutcomepQnxSKQu": [{
"Key": "Icon",
"Value": {
"DataType": "System.String",
"Field": "Icon",
"Value": "O"
}
}, {
"Key": "IconDescription",
"Value": {
"DataType": "System.String",
"Field": "IconDescription",
"Value": "Old"
}
}, {
"Key": "IconLongDescription",
"Value": {
"DataType": "System.String",
"Field": "IconLongDescription",
"Value": "Older"
}
}]
}
}
}
Ожидая получить
dynamic data = serializer.Deserialize(jsonText, typeof(object));
data.Response.Outcome.KeyValueOfstringOutcomepQnxSKQu["Icon"].Field.Value
Ожидаемое значение O
Ответ №1:
Вот одно из решений, использующее Json.NET:
dynamic data = JsonConvert.DeserializeObject(jsonText, typeof(object));
var list = data.Response.Outcome.KeyValueOfstringOutcomepQnxSKQu as IEnumerable<dynamic>;
var iconNode = list.FirstOrDefault(r => r.Key == "Icon");
var valueOfO = iconNode.Value.Value.Value;
Редактировать: Альтернативное решение: Поскольку ваши данные кажутся структурированными, и вы читаете жестко запрограммированные пути из json, я предпочту, чтобы вы создавали классы моделей вместо использования динамических объектов. Ниже приведен один из примеров рабочих классов модели, с помощью которых вы можете десериализовать JsonConvert.DeserializeObject<Rootobject>(jsonText)
public class Rootobject
{
public Response Response { get; set; }
}
public class Response
{
public Outcome Outcome { get; set; }
}
public class Outcome
{
public Keyvalueofstringoutcomepqnxskqu[] KeyValueOfstringOutcomepQnxSKQu { get; set; }
}
public class Keyvalueofstringoutcomepqnxskqu
{
public string Key { get; set; }
public Value Value { get; set; }
}
public class Value
{
public string DataType { get; set; }
public string Field { get; set; }
[JsonProperty("Value")]
public string Value1 { get; set; }
}
Комментарии:
1. Спасибо, Ристо, есть ли способ добиться этого: data.Response. Результат. Ключевое значение STRINGOUTCOMEPQNXSKQU как IEnumerable<dynamic>; путем передачи строки, из какого поля получить в качестве примера: var x = «Результат. Ключевое значение stringoutcomepqnxskqu как IEnumerable<dynamic>»; data.Response.x;
2. Я не понял вашего вопроса, как вы хотите передать строку?
3. Если вы имеете в виду, что «Значок» — текст в виде строки, вы можете преобразовать это в функцию, где вы передаете «Значок» в качестве параметра. Это то, что вы имели в виду?
4. Ристо, я не могу выполнить специальную вставку. Класс Value имеет свойство Value для него
5. Я обновил ответ, теперь есть примеры классов моделей (пожалуйста, обратите внимание
[JsonProperty("Value")]
— атрибут над именем-конфликтующее свойство.