0

The service I'm dealing returning different objects nested into a generic object. Here are sample mockup results from service

{"date":1591430887.591481,"results":[{"identity":"result_type_a","result":{"attr_a":1591427634}}]}
{"date":1591430887.591481,"results":[{"identity":"result_type_b","result":{"attr_b":1591427634,"attr_bb":3591457634}}]}
{"date":1591430887.591481,"results":[{"identity":"result_type_c","result":{"attr_c":1591427634,"attr_cc":3591457634,"attr_cc":59634}},{"identity":"result_type_d","result":{"attr_d":"rfrvr","attr_dd":"ytur"}}]}

I tried creating a generic object with declaring result attribute as string. And planning that I could deserialize to the returning json to that generic object, check identity attribute and deserilize the string in result attribute to specific object type.

Here is the object structure

public class GeneralResponse
{
    [JsonProperty("date")]
    public double Date { get; set; }
    [JsonProperty("results")]
    public List<GenericResults> Results { get; set; }


}
public class GenericResults
{
    [JsonProperty("identity")]
    public string Identity { get; set; }
    [JsonProperty("result")]
    public string Result { get; set; }
}

To serialize/deserialize I'm using Newtonsoft library and the code is below

    public static GeneralResponse SerializeResponse(string response)
    {
        return JsonConvert.DeserializeObject<GeneralResponse>(response);
    }

Unfortunately I got following exception while deserializing generic object.

"Unexpected character encountered while parsing value: {. Path 'results[0].result', line 1, position 71."

If I declare Result property of GenericResult as object as below

public class GenericResults
{
    [JsonProperty("identity")]
    public string Identity { get; set; }
    [JsonProperty("result")]
    public object Result { get; set; }
}

I can pass first serialization and make the second serialization without getting any exception.

        string inner_object = response.Result.ToString();
        switch (type)
        {               
            case ResponseTypes.type_A: return JsonConvert.DeserializeObject<ObjectTypeA>(inner_object);
            case ResponseTypes.type_B: return JsonConvert.DeserializeObject<ObjectTypeB>(inner_object);
            case ResponseTypes.type_C: return JsonConvert.DeserializeObject<ObjectTypeC>(inner_object);
            default: throw new Exception("Unknown Response Type");
        }

But returned object does not contain the data. I would appreciate any help about modeling this algorithm. Thanks in advance.

Anu Viswan
  • 17,797
  • 2
  • 22
  • 51
Emre
  • 3
  • 3
  • Looks like your `Result` should be a polymorphic type hierarchy. To deserialize such a type hierarchy see [Deserializing polymorphic json classes without type information using json.net](https://stackoverflow.com/q/19307752/3744182) and [How to implement custom JsonConverter in JSON.NET to deserialize a List of base class objects?](https://stackoverflow.com/q/8030538/3744182), of which this looks to be a duplicate. Agree? – dbc Jun 07 '20 at 14:59

2 Answers2

0

When you use string with JSON.NET serialization it is not actually using the JSON string but tries to parse a JSON string value.

You could use JObject instead, which is JSON.NETs wrapper for JSON objects. The JObject can then be used to deserialize into a type or by used to access JSON properties directly. Like this:

switch (type)
{               
    case ResponseTypes.type_A: return response.Result.ToObject<ObjectTypeA>(inner_object);
    case ResponseTypes.type_B: return response.Result.ToObject<ObjectTypeB>(inner_object);
    case ResponseTypes.type_C: return response.Result.ToObject<ObjectTypeC>(inner_object);
    default: throw new Exception("Unknown Response Type");
}
a-ctor
  • 3,568
  • 27
  • 41
  • I didn't know this. Tried this but didn't make a difference. Are there any other thing that I should change in code? – Emre Jun 07 '20 at 15:19
  • @Emre I have update my answert to include an example on how to convert a `JObject` by using `.ToObject`. – a-ctor Jun 07 '20 at 15:27
  • Thanks for the update but it didn't work. I guess inner_object sholdn't be there? – Emre Jun 07 '20 at 17:52
0

You could use a Dictionary to store the result, which looks to be polymorphic. For example,

   public partial class GeneralResponse
    {
        [JsonProperty("date")]
        public double Date { get; set; }

        [JsonProperty("results")]
        public ResultElement[] Results { get; set; }
    }

    public partial class ResultElement
    {
        [JsonProperty("identity")]
        public string Identity { get; set; }

        [JsonProperty("result")]
        public Dictionary<string,object> Result { get; set; }
    }

Working Demo

Output Sample

enter image description here

Anu Viswan
  • 17,797
  • 2
  • 22
  • 51
  • Thanks, It's a good idea but the object types are not dictionary actually. I simplified objects in order to focus on critical parts. – Emre Jun 07 '20 at 15:20