3

I'm trying to serialize a KeyValuePair property in C# that looks like this:

[JsonDisplayName("custom")]
public  KeyValuePair<string,string> Custom { get; set; }

to JSON by setting the property with:

MyClass.Custom = new KeyValuePair<string, string>("destination", destination);

But the output I get looks something like this:

"custom":{"Key":"destination","Value":"Paris"}

Instead I want:

"custom":{"destination":"Paris"}

Any ideas how? I'm using Compact Framework and Visual Studio 2008 so I prefer not to use any external library. You're help is greatly appreciated.

Update: I have to use my company's Model class which has a SetCustom method that throws an exception if I use a dictionary.

Alir Kahi
  • 1,264
  • 2
  • 15
  • 27
  • No it shouldn't be then the generated JSON would be illogical – Rahul Sep 09 '16 at 16:46
  • @Rahul Could you explain why it would be illogical? I can use any data structure I want. – Alir Kahi Sep 09 '16 at 16:48
  • Cause then it would be as if `destination` is the property and `paris` is the property value and not otherwise and thus the deserialization as well will fail. – Rahul Sep 09 '16 at 16:54
  • Try placing a dictionary rather then key-value pair. – Filip Cordas Sep 09 '16 at 18:05
  • Possible duplicate of [C# JSON Serialization of Dictionary into {key:value, ...} instead of {key:key, value:value, ...}](http://stackoverflow.com/questions/4861138/c-sharp-json-serialization-of-dictionary-into-keyvalue-instead-of-keyk) – johnny 5 Sep 09 '16 at 18:09
  • The class that I have to set the data up for has a method for setting a custom field that throws an exception when I use dictionaries. I probably had to mention that in the description. – Alir Kahi Sep 09 '16 at 18:20

3 Answers3

4

You can use dictionary instead of key value pair

public class A
{
    [JsonProperty("custom")]
    public Dictionary<string, string> Custom
    {
        get;
        set;
    }
}
public class Program
{
    public static void Main()
    {
        A custom = new A();
        custom.Custom = new Dictionary<string, string>(){
            {"destination1", "foo"},
            {"destination2", "bar"},
        };
        Console.WriteLine(JsonConvert.SerializeObject(custom));
    }
}

This will produce

{"custom":{"destination1":"foo","destination2":"bar"}}

Or if you want to stick with KeyValuePair you will need to create your own converter

public class A
{
    [JsonProperty("custom")]
    public KeyValuePair<string, string> Custom
    {
        get;
        set;
    }
}

class KeyValueStringPairConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        KeyValuePair<string, string> item = (KeyValuePair<string, string>)value;
        writer.WriteStartObject();
        writer.WritePropertyName(item.Key);
        writer.WriteValue(item.Value);
        writer.WriteEndObject();
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof (KeyValuePair<string, string>);
    }
}

public class Program
{
    public static void Main()
    {
        A custom = new A();
        JsonSerializerSettings settings = new JsonSerializerSettings{Converters = new[]{new KeyValueStringPairConverter()}};
        custom.Custom = new KeyValuePair<string, string>("destination", "foo");
        Console.WriteLine(JsonConvert.SerializeObject(custom, settings));
    }
}
Bob
  • 545
  • 3
  • 8
0

Don't forget download from NuGet Newtonsoft.Json

class Program
{
    static void Main(string[] args)
    {
        String [,] arr = new String[1,2];
        arr[0,0] = "Hello";
        arr[0,1] = "World";

        Console.WriteLine(JsonConvert.SerializeObject(arr));
        Console.ReadKey(true);
        //[["Hello","World"]]
    }
}
0

I had the same question as the OP and Bob's answer did the trick for me. Just wanted to share that the final code differs a bit if you're using System.Text.Json.Serialization in .NET Core / .NET 5+ instead of Newtonsoft.Json.

public class StringKeyValuePairConverter : JsonConverter<KeyValuePair<string, string>>
{
    public override KeyValuePair<string, string> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        throw new NotImplementedException();
    }

    public override void Write(Utf8JsonWriter writer, KeyValuePair<string, string> value, JsonSerializerOptions options)
    {
        writer.WriteStartObject();
        writer.WritePropertyName(value.Key);
        writer.WriteStringValue(value.Value);
        writer.WriteEndObject();
    }
}

It's mostly the same, except value is strongly typed, eliminating the need for a cast, and WriteStringValue (or the appropriate type-specific variant) is used instead of WriteValue.