1

I have a json that may look like the following:

{
  "description": "my description",
  "company": "my company"
}

Or

{
  "description": "my description",
  "company": {
    "name": "my company"
   }
}

How can I deserialize them to a model like below:

public class ResponseModel
{
     [JsonProperty("description")]
     public string Description {get; set;}
     [JsonProperty("company")] // and specify possible list of types as string or CompanyModel
     public object Company {get; set;}
}
Victor Mukherjee
  • 10,487
  • 16
  • 54
  • 97
  • 3
    There's no way to correct the source of the JSON to follow a consistent schema? If this is from some 3rd party then it's pretty sloppy and they should really fix it. – David Oct 20 '22 at 12:57
  • 2
    I'm pretty sure (not that I know direct link) it is duplicate of already existing question with custom `JsonConverter` as an answer – Selvin Oct 20 '22 at 12:57
  • @David this is what service-now api does :D – Victor Mukherjee Oct 20 '22 at 13:15
  • 1
    Does this answer your question? [Handling JSON single object and array](https://stackoverflow.com/questions/44100383/handling-json-single-object-and-array) – gilliduck Oct 20 '22 at 13:57

2 Answers2

0

I think you should do something like this:

First add annotation for Company property and create a helper model it

    public class ResponseModel
    {
        [JsonProperty("description")]
        public string Description { get; set; }
        [JsonProperty("company")] // and specify possible list of types as string or CompanyModel
        [JsonConverter(typeof(CompanyJsonConverter))] // add this line
        public string Company { get; set; }
    }

    public class CompanyHelperModel
    {
        public string name { get; set; }
    }

Then create the actual converter class (I sadly cannot test it right now, but the logic should be correct):

public class CompanyJsonConverter : JsonConverter
    {

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            // don't care
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            if (reader.ValueType == typeof(string)) return reader.ReadAsString();

            return JsonConvert.DeserializeObject<CompanyHelperModel>(reader.ReadAsString()).name;
        }

        public override bool CanConvert(Type objectType)
        {
            return true;
        }
    }

And that's it! I assumed that you need only to read it, not write it.

Karel Křesťan
  • 399
  • 2
  • 17
0

I usually use a JsonConstructor

public class ResponseModel
{
    [JsonProperty("description")]
    public string Description { get; set; }
    
    public Company Company { get; set; }

    [JsonConstructor]
    public ResponseModel(JToken company)
    {
        if ( company.Type == JTokenType.String )
            Company = new Company { Name = (string) company };
        else Company = company.ToObject<Company>();
    }
}

public class Company
{
    [JsonProperty("name")]
    public string Name { get; set; }
}
Serge
  • 40,935
  • 4
  • 18
  • 45