5

I'm trying to write some C# wrapper classes for JSON that I need to send/receive. In one instance, I'm receiving a multi-dimensional array of mixed types:

stops: [
    [0.1, "#55BF3B"],
    [0.5, "#DDDF0D"],
    [0.9, "#DF5353"]
 ]

How can this be represented in a class property?

[JsonProperty("stops")]
public WhatType?[] Stops { get; set; }

What I'd really like is a class like the following:

public class Stop
{
    public decimal Value { get; set; }
    public string Color { get; set; }
}

That would serialize/deserialize as an array (without property names):

[.1, "#000000"]

Then my Stops property could simply be an array of Stop. However, I'm not sure this is possible even with a custom converter. Any ideas?

0

1 Answer 1

10

Yes, this is pretty much a textbook example of a situation where you would use a JsonConverter.
Here is what the code would look like:

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

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JArray ja = JArray.Load(reader);
        Stop stop = new Stop();
        stop.Value = (decimal)ja[0];
        stop.Color = (string)ja[1];
        return stop;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        JArray ja = new JArray();
        Stop stop = (Stop)value;
        ja.Add(stop.Value);
        ja.Add(stop.Color);
        ja.WriteTo(writer);
    }
}

To use the converter, simply decorate your Stop class with a [JsonConverter] attribute like this:

[JsonConverter(typeof(StopConverter))]
public class Stop
{
    public decimal Value { get; set; }
    public string Color { get; set; }
}

Then, everything should "just work". Here is a round-trip demo:

class Program
{
    static void Main(string[] args)
    {
        string json = @"
        { 
            ""stops"": 
            [
                [0.1, ""#55BF3B""],
                [0.5, ""#DDDF0D""],
                [0.9, ""#DF5353""]
            ]
        }";

        RootObject obj = JsonConvert.DeserializeObject<RootObject>(json);
        foreach (Stop stop in obj.Stops)
        {
            Console.WriteLine("Value: " + stop.Value);
            Console.WriteLine("Color: " + stop.Color);
            Console.WriteLine();
        }

        json = JsonConvert.SerializeObject(obj, Formatting.Indented);
        Console.WriteLine(json);
    }
}

class RootObject
{
    [JsonProperty("stops")]
    public List<Stop> Stops { get; set; }
}

[JsonConverter(typeof(StopConverter))]
public class Stop
{
    public decimal Value { get; set; }
    public string Color { get; set; }
}

Output:

Value: 0.1
Color: #55BF3B

Value: 0.5
Color: #DDDF0D

Value: 0.9
Color: #DF5353

{
  "stops": [
    [
      0.1,
      "#55BF3B"
    ],
    [
      0.5,
      "#DDDF0D"
    ],
    [
      0.9,
      "#DF5353"
    ]
  ]
}

Fiddle: https://dotnetfiddle.net/6XcY9r

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

3 Comments

Awesome Brian, Thanks! My next step is to set the color property to System.Drawing.Color, which should be easy enough in the converter.
No problem; glad to help.
Just a question, how to call/get/return the specific Value or Color, can you update your post if possible?

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.