0

Using Json.NET 10.0.3. Consider the following sample:

class Foo
{
   [JsonProperty("ids")]
   public int[] MyIds { get; set; }
}

Obviously, the elements of the array are unnamed. Now consider the following json:

{
  "ids": [{
      "id": 1
    }, {
      "id": 2
    }
  ]
}

And then we try to parse it:

var json = @"{""ids"":[{""id"":1},{""id"":2}]}";
var result = JsonConvert.DeserializeObject<Foo>(son);

Parsing the above fails with the following message:

Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: {. Path 'ids', line 1, position 9.

I know I can wrap int in a class and name it "id" there, but I'm wondering if this can be done without this extra work. The reason being what appears to be a limitation in SQL Server 2016. See this question.

3
  • Obvious thing to do would be to use a custom JsonConverter. Commented Jan 13, 2018 at 20:21
  • But with a custome converter your C# wouldn't match your JS. I suppose it depends on where you want to lie. Commented Jan 13, 2018 at 20:33
  • @HenkHolterman Not sure if "" is that much better than \". Commented Jan 13, 2018 at 20:36

1 Answer 1

2

You can make a custom JsonConverter to translate between the two array formats:

class CustomArrayConverter<T> : JsonConverter
{
    string PropertyName { get; set; }

    public CustomArrayConverter(string propertyName)
    {
        PropertyName = propertyName;
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JArray array = new JArray(JArray.Load(reader).Select(jo => jo[PropertyName]));
        return array.ToObject(objectType, serializer);
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        IEnumerable<T> items = (IEnumerable<T>)value;
        JArray array = new JArray(
            items.Select(i => new JObject(
                new JProperty(PropertyName, JToken.FromObject(i, serializer)))
            )
        );
        array.WriteTo(writer);
    }

    public override bool CanConvert(Type objectType)
    {
        // CanConvert is not called when the [JsonConverter] attribute is used
        return false;
    }
}

To use the converter, mark your array property with a [JsonConverter] attribute as shown below. Note the type parameter for the converter must match the item type of the array, and the second parameter of the attribute must be the property name to use for the values in the JSON array.

class Foo
{
    [JsonProperty("ids")]
    [JsonConverter(typeof(CustomArrayConverter<int>), "id")]
    public int[] MyIds { get; set; }
}

Here is a round-trip demo: https://dotnetfiddle.net/vUQKV1

Sign up to request clarification or add additional context in comments.

2 Comments

this is briliant @Brian.
Hi I have a similar question here stackoverflow.com/posts/59369351. If you are monitoring Brian could you take a look please?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.