Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ServiceStack.Text serializing dictionaries

Tags:

servicestack

I was using Json.Net to serialize dictionaries of type Dictionary, and when I added integers or booleans to the dictionary, when deserializing I would get integers and booleans back. Now I was trying to change my code to use ServiceStack.Text instead because of a problem in other part of the code with the serialization of dates, but now I get the booleans an integers as strings after deserialization. Is there any way to have the same behaviour as Json.Net?

Here's the code to reproduce it: https://gist.github.com/1608951 Test_JsonNet passes, but both Test_ServiceStack_Text_TypeSerializer and Test_ServiceStack_Text_JsonSerializer fail

like image 966
Gustavo Guerra Avatar asked Jan 13 '12 10:01

Gustavo Guerra


2 Answers

For untyped dynamic payloads it's better to use the JSON Utils in ServiceStack.Common which lets you parse dynamic payloads whilst preserving their type, e.g:

var obj = JSON.parse(json);
if (obj is new Dictionary<string, object> jsonObj) 
{
    int b = (int)jsonObj["b"];
    bool c = (bool)jsonObj["c"];
}

It's a purposeful design decision in ServiceStack.Text JSON Serializer that no type information is emitted for primitive value types which is why the values are left as strings.

You either have to deserialize into a strong typed POCO that holds the type info:

public class MixType
{
    public string a { get; set; }
    public int b { get; set; }
    public bool c{ get; set; }
}

var mixedMap = new Dictionary<string, object> {
    { "a", "text" },
    { "b", 32 },
    { "c", false },
};

var json = JsonSerializer.SerializeToString(mixedMap);
Console.WriteLine("JSON:\n" + json);

var mixedType = json.FromJson<MixType>();
Assert.AreEqual("text", mixedType.a);
Assert.AreEqual(32, mixedType.b);
Assert.AreEqual(false, mixedType.c);

Or deserialize into a Dictionary<string,string> and parse into specific types yourself.

Or deserialize using ServiceStack's dynamic API. See ServiceStack's Dynamic JSON Test folder for examples on how to do this.

like image 184
mythz Avatar answered Oct 01 '22 12:10

mythz


You can now do this:

JsConfig.TryToParsePrimitiveTypeValues = true;

Which will make the JSON deserialiser try to determine what the types should be, and you will get your integers back as integers, booleans back as booleans, etc.

like image 31
Cocowalla Avatar answered Oct 01 '22 14:10

Cocowalla