We use nested JsonObjects in our DTOs in order to have a dynamic object, Sometimes customers post data like “http://myuri.de” but in this case we run into an issue that:
var o = new JsonObject();
o.Add("url", @"http:\/\/myuri.de");
Console.WriteLine(o.ToJson());
we will get (escaped backslash):
{"url":"http:\\/\\/myuri.de"}
instead of:
{"url":"http:\/\/myuri.de"}
or better
{"url":"http://myuri.de"} like with Console.WriteLine(o["url"])
yes sounds logical, but if we use ExpandoObject instead of JsonObject we doesn’t run in this issue:
var b = @"{""url"":""http:\/\/myuri.de""}";
var jObj = ServiceStack.Text.JsonSerializer.DeserializeFromString<ExpandoObject>(b);
Console.WriteLine(ServiceStack.Text.JsonSerializer.SerializeToString(jObj));
What issue, if "http:\/\/myuri.de" unescapes to c# string http://myuri.de, if you don’t want the back slashes don’t add them, they’re already not needed.
… normally I expect that if someone sends data with e.g. “http://myuri.de” to our REST API the minimum is that after deserialization and working with the deserialized data and then serialize it back to Json… I at least expect to get the same data back => “http://myuri.de” ?
I think you mean that the contents in JsonObject are stored unescaped, that’s just how it works, you’d use the APIs to retrieve escaped values from it, e.g:
var url = jsonObj.Get("url");
Otherwise you can just deserialize it into a string dictionary:
var strDict = b.FromJson<Dictionary<string,string>>();
…the nested JsonObject in our DTOs are like pass through parameter so if a consumer saves an object via our REST API, he would like to get the same thing back again …
REST API POST "http:\/\/myuri.de"
=> REST API GET "http:\/\/myuri.de" and not REST API GET "http:\\/\\/myuri.de"
We have to consider that slashes are passed escaped to our API, since escaping slashes is vailid (but optional). I think the underlying problem is that consecutive (de-)serializaition via JsonObject
var s0 = @"{""escapeTest"":"" / \/ \""test\"" \\ ""}";
Console.WriteLine(s0);
var s1 = JsonSerializer.SerializeToString(JsonSerializer.DeserializeFromString<JsonObject>(s0));
Console.WriteLine(s1);
var s2 = JsonSerializer.SerializeToString(JsonSerializer.DeserializeFromString<JsonObject>(s1));
Console.WriteLine(s2);
var s3 = JsonSerializer.SerializeToString(JsonSerializer.DeserializeFromString<JsonObject>(s2));
Console.WriteLine(s3);
results in backslashes multiplied by a power of 2:
Right you don’t want to be using JsonObject for serialization, it’s not a dynamic object, it’s a wrapper around Dictionary<string,string> that holds unescaped string values that you can choose to access both the escaped an unescaped values out with obj.Get() and obj.GetUnescaped().
You should use Dictionary<string,string> where it’s appropriate. ServiceStack also supports object types which is more “dynamic” since it will return the actual .NET Data Structure instead of coercing everything into a Dictionary<string,string> however using dynamic object is poor API design that ideally should not be your Service Contracts.
var b = @"{""url"":""http:\/\/myuri.de""}";
var jObj = ServiceStack.Text.JsonSerializer.DeserializeFromString<Object>(b);
Console.WriteLine(ServiceStack.Text.JsonSerializer.SerializeToString(jObj));
we get:
"{url:http://myuri.de}"
instead
{"url":"http:\/\/myuri.de"} or {"url":"http://myuri.de"}
It works differently in ServiceStack Services because it replaces the implementation of ServiceStack.Text object handling with JS Utils which is in ServiceStack.Common.
You can test it with:
var obj = JSON.parse(@"{""url"":""http:\/\/myuri.de""}") as Dictionary<string,object>;
But you’ll still get unescaped string, i.e:
[url, http://myuri.de]
To hookup the different serialization behavior in ServiceStack.Text:
Hi, I’ve one more question is there any way to get an Exception instead of 0 after deserialize to Dictionary<string,object> in the following example (number with 2 decimal points ):
JS.Configure();
var obj = JSON.parse(@"{""test"":23.34.3333}") as Dictionary<string,object>;