0

I'm trying to ready a JSON file with contents similar to this:

{
  "result": {
    "1357": {
      "icon": "smiley-face",
      "name": "happy"
    },
    "success": true
  }
}

This example below works but the problem I'm having is that the property name for classid is always different. How can I deserialize the classid without knowing the property name?

using System;
using System.IO;
using Newtonsoft.Json;

public class ClassId
{
    [JsonProperty("icon")]
    public string Icon { get; set; }

    [JsonProperty("name")]
    public string Name { get; set; }
}

public class Result
{
    [JsonProperty("1357")] // this key is always different
    public ClassId classid { get; set; }

    [JsonProperty("success")]
    public bool Success { get; set; }
}

public class Example
{
    [JsonProperty("result")]
    public Result Result { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        var json = File.ReadAllText("test.json");
        var container = JsonConvert.DeserializeObject<Example>(json);
        Console.WriteLine(container.Result.classid.Icon);
    }
}
Brian Rogers
  • 125,747
  • 31
  • 299
  • 300
ramafe
  • 123
  • 13

2 Answers2

1

Normally, when the keys in the JSON can change, you can handle it by using a Dictionary<string, T> in place of a regular class. See this question for an example of what I mean. However, this approach will not work in your case because you also have a boolean success flag as part of your result, and that will not mix with a Dictionary<string, ClassId>. So, instead, you will need to use a JsonConverter to deserialize your Result class. Here is the code you will need:

class ResultConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(Result);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject obj = JObject.Load(reader);
        Result result = new Result();
        result.Success = (bool)obj["success"];
        JProperty prop = obj.Properties().FirstOrDefault(p => p.Name != "success");
        if (prop != null)
        {
            result.classid = prop.Value.ToObject<ClassId>(serializer);
        }
        return result;
    }

    public override bool CanWrite
    {
        get { return false; }
    }

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

To use it, add a [JsonConverter] attribute to your Result class like this:

[JsonConverter(typeof(ResultConverter))]
public class Result
{
    ...
}

Fiddle: https://dotnetfiddle.net/ACR5Un

Community
  • 1
  • 1
Brian Rogers
  • 125,747
  • 31
  • 299
  • 300
0

You won't be able to do this using JsonConvert.DeserializeObject; you might need to create a JsonReader to implement this logic.

Steve Cooper
  • 20,542
  • 15
  • 71
  • 88