Deserializing strings into objects with Json.NET

I’m working on a library to parse Minecraft JSON files. However, they have a slightly weird format that I can’t figure out how to parse with Newtonsoft’s JSON.net:

{
    "values": [
        "some_object",
        "another_object",
        {
            "name": "third_object",
            "required": false
        }
    ]
}

The class I’m trying to deserialize the values array into looks like this:

class TagValue
{
    public string Name;
    public bool Required = false;
}

So for values which are just a string, it should set Name to the string and leave Required as false.

Is there a way I can do this? I’m very new to the library and can’t figure out how to do anything more advanced than the most basic deserialization.

>Solution :

Try this

[JsonConverter(typeof(TagValueConverter))]
class TagValue
{
    [JsonProperty("name")]
    public string Name { get; set; }

    [JsonProperty("required")]
    public bool Required { get; set; }

    private class TagValueConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return objectType == typeof(string) ||
                objectType == typeof(TagValue);
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            if (reader.TokenType == JsonToken.String)
                return new TagValue
                {
                    Name = reader.Value as string
                };
            else
            {
                var jobj = JObject.Load(reader);
                var obj = new TagValue();
                serializer.Populate(jobj.CreateReader(), obj);
                return obj;
            }
        }

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            throw new NotImplementedException();
        }
    }
}

Then presumably you have/need a class for the outer object:

class TagValues
{
    [JsonProperty("values")]
    public TagValue[] Values { get; set; }

    public static void TestMe()
    {
        string json = @"{
            ""values"": [
                ""some_object"",
                ""another_object"",
                {
                    ""name"": ""third_object"",
                    ""required"": true
                }
            ]
        }";

        var tags = JsonConvert.DeserializeObject<TagValues>(json);

        Debug.Assert(tags.Values?.Length == 3);
        Debug.Assert(tags.Values[0].Name == "some_object");
        Debug.Assert(tags.Values[1].Name == "another_object");
        Debug.Assert(tags.Values[2].Name == "third_object" &&
                    tags.Values[2].Required == true);
    }
}

PS – You also should make those fields properties as was suggested in the comments.

Leave a Reply