0

I have the use case where I need to deserialize json into an object. The json is as follows

{
    "additionalAttributes": [
        {
            "name": "type",
            "value": "action"
        },
        {
            "name": "pages",
            "value": [                
                "34",
                "39",
                "43"
            ]
        },
        {
            "name": "chapters",
            "value": [                
                "The dawn of time",
                "The end of the world"
            ]
        }
   ]
}

The difficult part is that value is either a string or an array of strings. The resulting object should have an array of strings, even if there is only one string in it.

How can I do this with json.net? The deserializer complains that the first value is not an array of strings.

I cannot change the source json.

Many thanks Maarten

  • With a case like this, it seems like it would be optimal to just use a `JObject` instead of trying to define complex contracts in C#'s typing system. Performance hit would be negligible compared to the complexity of trying to add custom logic to serialization/deserialization – gabriel.hayes Jan 24 '20 at 19:23
  • Have you looked at this? https://stackoverflow.com/questions/40118012/check-jobject-contains-an-array?rq=1 That gives you what you need – Train Jan 24 '20 at 19:25
  • 3
    Add `[JsonConverter(typeof(SingleOrArrayConverter))]` to your `value` property as shown in [How to handle both a single item and an array for the same property using JSON.net](https://stackoverflow.com/q/18994685/3744182). – dbc Jan 24 '20 at 19:32

1 Answers1

-1

String and string arrays both inherit from object. So your model can look like this

public class AdditionalAttribute
{
    public string name { get; set; }
    public object value { get; set; }
}

Then you would have to unbox the object to one of the two types.

Another option is to define value as partial struct with implicit operators, like below

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

    [JsonProperty("value")]
    public Value Value { get; set; }
}

public partial struct Value
{
    public string _value;
    public List<string> _valueArray;

    public static implicit operator Value(string value) => new Value { _value = value};
    public static implicit operator Value(List<string> valueArray) => new Value { _valueArray= valueArray};
}
NotTheBatman
  • 132
  • 6
  • 2
    This does not work with the string and List. Your comment about using only object / dynamic as the type works but not with type Value. – Jawad Jan 24 '20 at 20:19
  • Using `object` will not work. .NET JSON serialize deserializes to `JsonElement` whenever it sees `object`. Just as `Json.Net` would deserialize this to `JObject`/`JArray`. – Sergej Christoforov Mar 22 '21 at 15:44