Omar
Omar

Reputation: 40202

JSON.NET deserialize a specific property

I have the following JSON text:

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

I want to deserialize PropOne into type PropOneClass without the overhead of deserializing any other properties on the object. Can this be done using JSON.NET?

Upvotes: 36

Views: 55035

Answers (6)

hultqvist
hultqvist

Reputation: 18511

Matt's answer is by far the fastest solution though it has a bug. This is my attempt in fixing that. This method will only return a matching property at the root level. There is still a naive approach in counting start and end tokens though for valid JSON it will probably work.

Matt, feel free to copy this into your answer.

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);
    }
}

Upvotes: 2

hultqvist
hultqvist

Reputation: 18511

A simpler solution to Omar's answer would be to have a wrapper.

class Wrapper
{
    public PropOneClass PropOne;
}

JsonConvert.Deserialize<Wrapper>(json).PropOne

My tests found it to be about 30% faster.

Upvotes: 18

Omar
Omar

Reputation: 40202

The JSON isn't too large, so I'll take Matt Johnson's suggestion and deserialize the whole thing. Thanks to jcwrequests answer, I was able to use this method:

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

Upvotes: 46

Matt Johnson-Pint
Matt Johnson-Pint

Reputation: 241808

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"
}

This approach avoids having to deserialize the entire object. But note that this will only improve performance if the json is significantly large, and the property you are deserializing is relatively early in the data. Otherwise, you should just deserialize the whole thing and pull out the parts you want, like jcwrequests answer shows.

Upvotes: 37

jcwrequests
jcwrequests

Reputation: 1130

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

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

Using JSON Linq provider you do not need to deserialize the object into a known type.

Upvotes: 7

NomadTraveler
NomadTraveler

Reputation: 1084

Use JsonIgnore - this will cause the property to be completely ignored by Json.Net, both for serializing and deserializing.

Also, check this link.

Upvotes: 1

Related Questions