Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make ASP.NET WCF convert dictionary to JSON, omitting "Key" & "Value" tags

Here's my dilemma. I'm using a RESTful ASP.NET service, trying to get a function to return a JSON string in this format:

{"Test1Key":"Test1Value","Test2Key":"Test2Value","Test3Key":"Test3Value"} 

But I'm getting it in this format instead:

[{"Key":"Test1Key","Value":"Test1Value"}, {"Key":"Test2Key","Value":"Test2Value"}, {"Key":"Test3Key","Value":"Test3Value"}] 

My method looks like this:

[OperationContract] [WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.WrappedRequest, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)] public Dictionary<string, string> Test(String Token) {     if (!IsAuthorized(Token))         return null;      if (!IsSecure(HttpContext.Current))         return null;      Dictionary<string, string> testresults = new Dictionary<string, string>();     testresults.Add("Test1Key", "Test1Value");     testresults.Add("Test2Key", "Test2Value");     testresults.Add("Test3Key", "Test3Value");     return testresults; } 

Is there any way I can get rid of those "Key" and "Value" tags using only built in ASP.NET tools? (i.e., I'd rather not use JSON.NET, if it's avoidable)

Thanks very much! :)

like image 511
Katherine Williams Avatar asked Sep 28 '11 21:09

Katherine Williams


2 Answers

The .NET dictionary class won't serialize any other way than the way you described. But if you create your own class and wrap the dictionary class then you can override the serializing/deserializing methods and be able to do what you want. See example below and pay attention to the "GetObjectData" method.

    [Serializable]     public class AjaxDictionary<TKey, TValue> : ISerializable     {         private Dictionary<TKey, TValue> _Dictionary;         public AjaxDictionary()         {             _Dictionary = new Dictionary<TKey, TValue>();         }         public AjaxDictionary( SerializationInfo info, StreamingContext context )         {             _Dictionary = new Dictionary<TKey, TValue>();         }         public TValue this[TKey key]         {             get { return _Dictionary[key]; }             set { _Dictionary[key] = value; }         }         public void Add(TKey key, TValue value)         {             _Dictionary.Add(key, value);         }         public void GetObjectData( SerializationInfo info, StreamingContext context )         {             foreach( TKey key in _Dictionary.Keys )                 info.AddValue( key.ToString(), _Dictionary[key] );         }     } 
like image 50
Markis Avatar answered Oct 11 '22 02:10

Markis


Expanding slightly on @MarkisT's excellent solution, you can modify the serialization constructor to recreate one of these dictionaries from the same JSON (thus allowing you to take an AjaxDictionary as a service parameter), as follows:

public AjaxDictionary( SerializationInfo info, StreamingContext context ) {      _Dictionary = new Dictionary<TKey, TValue>();       foreach (SerializationEntry kvp in info)      {          _Dictionary.Add((TKey)Convert.ChangeType(kvp.Name, typeof(TKey)), (TValue)Convert.ChangeType(kvp.Value, typeof(TValue)));      } } 
like image 41
Dan Parsonson Avatar answered Oct 11 '22 03:10

Dan Parsonson