C# JSON Serialization of Dictionary into {key:value, ...} instead of {key:key, value:value, ...}

166,972

Solution 1

Json.NET does this...

Dictionary<string, string> values = new Dictionary<string, string>();
values.Add("key1", "value1");
values.Add("key2", "value2");

string json = JsonConvert.SerializeObject(values);
// {
//   "key1": "value1",
//   "key2": "value2"
// }

More examples: Serializing Collections with Json.NET

Solution 2

use property UseSimpleDictionaryFormat on DataContractJsonSerializer and set it to true.

Does the job :)

Solution 3

I'm using out of the box MVC4 with this code (note the two parameters inside ToDictionary)

 var result = new JsonResult()
 {
     Data = new
     {
         partials = GetPartials(data.Partials).ToDictionary(x => x.Key, y=> y.Value)
     }
 };

I get what's expected:

{"partials":{"cartSummary":"\u003cb\u003eCART SUMMARY\u003c/b\u003e"}}

Important: WebAPI in MVC4 uses JSON.NET serialization out of the box, but the standard web JsonResult action result doesn't. Therefore I recommend using a custom ActionResult to force JSON.NET serialization. You can also get nice formatting

Here's a simple actionresult JsonNetResult

http://james.newtonking.com/archive/2008/10/16/asp-net-mvc-and-json-net.aspx

You'll see the difference (and can make sure you're using the right one) when serializing a date:

Microsoft way:

 {"wireTime":"\/Date(1355627201572)\/"}

JSON.NET way:

 {"wireTime":"2012-12-15T19:07:03.5247384-08:00"}

Solution 4

In .NET 5 and later, you can simply write:

using System;
using System.Collections.Generic;
                    
public class Program
{
    public static void Main()
    {
        Dictionary<string, string> values = new();
        values.Add("key1", "value1");
        values.Add("key2", "value2");

        string json = System.Text.Json.JsonSerializer.Serialize(values);
        Console.WriteLine(json);
    }
}

to get {"key1":"value1","key2":"value2"}.

No external dependency is needed.

Solution 5

Unfortunately, this is not currently possible in the latest version of DataContractJsonSerializer. See: http://connect.microsoft.com/VisualStudio/feedback/details/558686/datacontractjsonserializer-should-serialize-dictionary-k-v-as-a-json-associative-array

The current suggested workaround is to use the JavaScriptSerializer as Mark suggested above.

Good luck!

Share:
166,972

Related videos on Youtube

Aaaaaaaa
Author by

Aaaaaaaa

Updated on July 05, 2022

Comments

  • Aaaaaaaa
    Aaaaaaaa almost 2 years

    Is it possible to serialize a .Net Dictionary<Key,Value> into JSON with DataContractJsonSerializer that is of the format:

    {
      key0:value0,
      key1:value1,
      ...
    }
    

    I use Dictionary <K,V>, because there is not predefined structure of the inputs.

    I'm interesting just for DataContractJsonSerializer result! I've already found a "Surrogate" example, but there is an additional "data" in the output, and if the dictionary <K, String> is, the escaping is false too.


    I've found the solution, what a needed! First of all, a serializable "dictionary" class: (Of course, this sample works just in one way, but I dont't need deserialization)

    [Serializable]
    public class MyJsonDictionary<K, V> : ISerializable {
        Dictionary<K, V> dict = new Dictionary<K, V>();
    
        public MyJsonDictionary() { }
    
        protected MyJsonDictionary( SerializationInfo info, StreamingContext context ) {
            throw new NotImplementedException();
        }
    
        public void GetObjectData( SerializationInfo info, StreamingContext context ) {
            foreach( K key in dict.Keys ) {
                info.AddValue( key.ToString(), dict[ key ] );
            }
        }
    
        public void Add( K key, V value ) {
            dict.Add( key, value );
        }
    
        public V this[ K index ] {
            set { dict[ index ] = value; }
            get { return dict[ index ]; }
        }
    }
    

    Usage:

    public class MainClass {
        public static String Serialize( Object data ) {
            var serializer = new DataContractJsonSerializer( data.GetType() );
            var ms = new MemoryStream();
            serializer.WriteObject( ms, data );
    
            return Encoding.UTF8.GetString( ms.ToArray() );
        }
    
        public static void Main() {
            MyJsonDictionary<String, Object> result = new MyJsonDictionary<String, Object>();
            result["foo"] = "bar";
            result["Name"] = "John Doe";
            result["Age"] = 32;
            MyJsonDictionary<String, Object> address = new MyJsonDictionary<String, Object>();
            result["Address"] = address;
            address["Street"] = "30 Rockefeller Plaza";
            address["City"] = "New York City";
            address["State"] = "NY";
    
            Console.WriteLine( Serialize( result ) );
    
            Console.ReadLine();
        }
    }
    

    And the result:

    {
          "foo":"bar",
          "Name":"John Doe",
          "Age":32,
          "Address":{
             "__type":"MyJsonDictionaryOfstringanyType:#Json_Dictionary_Test",
             "Street":"30 Rockefeller Plaza",
             "City":"New York City",
             "State":"NY"
          }
       }
    
    • Marc Gravell
      Marc Gravell over 13 years
      Any specific reason you want to limit to DataContractJsonSerializer ? Every time I've done a comparison (which is several times : I'm very "into" my serializers) this is the least preferable JSON tool for .NET; I always look at JavaScriptSerializer or JSON.Net
    • Shiv Kumar
      Shiv Kumar over 13 years
      In what context are you using this? That is is this a WCF app, ASP.NET app or something else. Are you using the DataContractJsonSerilizer in such as way that you're calling the WriteObject yourself or is some framework doing it for you?
    • Shiv Kumar
      Shiv Kumar over 13 years
      What's not clear in your post is that you want 1 JSON object with properties (and their values) being the name/value pairs in the dictionary. Either that or something is wrong since it can't be a JSON array since you can't have a JSON array where each element in the array has different property names. So can you be clear about the actual format you're looking to get?
    • Aaaaaaaa
      Aaaaaaaa over 13 years
      Hi Shiv Kumar: I call the WriteObject, why? And in one run I have the elements with the same structure, but this structure is not predefined, that's why I can't do a class for it. The DataContractJsonSerializer has company-reasons... :)
    • erikkallen
      erikkallen over 13 years
      @Shiv Kumar: Yes, it is definitely possible to have a JSON array with different property names. This actually happens every time you choose to omit properties with null values from the JSON.
    • drzaus
      drzaus over 10 years
      Anyone figured out the opposite? As in, how to get it to deserialize MyJsonDictionary properly?
    • Liam
      Liam over 10 years
      You shouldn't answer your own question in an edit. Instead actually add an answer, please edit your question and add the answer, as an answer
    • Michael Freidgeim
      Michael Freidgeim over 6 years
  • sandeep talabathula
    sandeep talabathula over 7 years
    2nd line should be string values = JsonConvert.SerializeObject(values);
  • vinhent
    vinhent about 7 years
    how can you set that settings for the default behavior of wcf when serializing the http response ?
  • SharpC
    SharpC over 6 years
    Worked for me, thanks! I had to use config.Formatters.JsonFormatter.UseDataContractJsonSerialize‌​r = true; in WebApiConfig.cs.