Подтвердить что ты не робот

JSON.NET десериализует определенное свойство

У меня есть следующий текст JSON:

{
    "PropOne": {
        "Text": "Data"
    }
    "PropTwo": "Data2"
}    

Я хочу десериализовать PropOne в тип PropOneClass без накладных расходов при десериализации любых других свойств объекта. Можно ли это сделать с помощью JSON.NET?

4b9b3361

Ответ 1

public T GetFirstInstance<T>(string propertyName, string json)
{
    using (var stringReader = new StringReader(json))
    using (var jsonReader = new JsonTextReader(stringReader))
    {
        while (jsonReader.Read())
        {
            if (jsonReader.TokenType == JsonToken.PropertyName
                && (string)jsonReader.Value == propertyName)
            {
                jsonReader.Read();

                var serializer = new JsonSerializer();
                return serializer.Deserialize<T>(jsonReader);
            }
        }
        return default(T);
    }
}

public class MyType
{
    public string Text { get; set; }
}

public void Test()
{
    string json = "{ \"PropOne\": { \"Text\": \"Data\" }, \"PropTwo\": \"Data2\" }";

    MyType myType = GetFirstInstance<MyType>("PropOne", json);

    Debug.WriteLine(myType.Text);  // "Data"
}

Этот подход позволяет избежать десериализации всего объекта. Но учтите, что это только улучшит производительность, если json значительно большой, а свойство, которое вы десериализуете, относительно рано в данных. В противном случае вам следует просто десериализовать все это и вытащить нужные вам части, как показывает ответ jcwrequests.

Ответ 2

JSON не слишком большой, поэтому я возьму предложение Мэтта Джонсона и десериализую все это. Благодаря ответу jcwrequests, я смог использовать этот метод:

var jObject = JObject.Parse(json);
var jToken = jObject.GetValue("PropTwo");
PropTwoClass value = jToken.ToObject(typeof(PropTwoClass));

Ответ 3

Более простое решение ответа Омара должно состоять в обертке.

class Wrapper
{
    public PropOneClass PropOne;
}

JsonConvert.Deserialize<Wrapper>(json).PropOne

Мои тесты показали, что он примерно на 30% быстрее.

Ответ 4

 var json = "{ "PropOne": { "Text": "Data" } "PropTwo": "Data2" }";

 JObject o = JObject.Parse(json);
 var val = o.PropTwo;

Используя поставщика JSON Linq, вам не нужно десериализовать объект на известный тип.

Ответ 5

Используйте JsonIgnore - это приведет к тому, что свойство JSP.Net полностью игнорируется как для сериализации, так и для десериализации.

Также проверьте эту ссылку .

Ответ 6

Ответ Matt является самым быстрым решением, хотя у него есть ошибка. Это моя попытка исправить это. Этот метод возвращает только свойство соответствия на корневом уровне. По-прежнему существует наивный подход при подсчете начальных и конечных токенов, хотя для действительного JSON он, вероятно, будет работать.

Мэтт, не стесняйтесь скопировать это в свой ответ.

public T GetFirstInstance<T>(string propertyName, string json)
{
    using (var stringReader = new StringReader(json))
    using (var jsonReader = new JsonTextReader(stringReader))
    {
        int level = 0;

        while (jsonReader.Read())
        {
            switch (jsonReader.TokenType)
            {
                case JsonToken.PropertyName:
                    if (level != 1)
                        break;
                    if ((string)jsonReader.Value == propertyName)
                    {
                        jsonReader.Read();

                        return (T)jsonReader.Value; 
                    }
                    break;

                case JsonToken.StartArray:
                case JsonToken.StartConstructor:
                case JsonToken.StartObject:
                    level++;
                    break;

                case JsonToken.EndArray:
                case JsonToken.EndConstructor:
                case JsonToken.EndObject:
                    level--;
                    break;
            }

        }
        return default(T);
    }
}