Получить значение свойства из динамического объекта

#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")] — атрибут над именем-конфликтующее свойство.