They seem to be the same thing at the first look. Because JsonObject : IDictionary<string, string>
. However, when I try to deserialize the follow sample data, I get different results:
var str1 = "{\"employees\": [" +
"{ \"firstName\":\"John\" , \"lastName\":\"Doe\" }, " +
"{ \"firstName\":\"Anna\" , \"lastName\":\"Smith\" }, " +
"{ \"firstName\":\"Peter\" , \"lastName\":\"Jones\" }" +
"]}";
//first try
public static JsonObject DeserializeJsonString(this string s) {
return JsonObject.Parse(s);
}
//second try
public static T DeserializeJson<T>(this string s) where T : class {
return JsonSerializer.DeserializeFromString<T>(s);
}
First try JsonObject.Parse()
:
- works fine and parse the object correctly.
Second try JsonSerializer.DeserializeFromString<Dictionary<string, string>>()
:
- gives me key value pair of "employees" and "[{" which seems to be the beginning fragment of the the actual value and the rest of the data chunk is missing.
Why do I have bad data in the 2nd way?
EDIT -------------------------------------------------------
NO LONGER AN ISSUE.
Latest version of SS has patched this problem. Now it can parse Dictionary<string, string>
just fine.
2 Answers 2
//Source code in ServiceStack.Text -> DeserializeDictionary.cs
//Line 89
//if type is JsonObject : Dictionary<string, string>
var mapKey = keyValue;
var mapValue = elementValue;
//Line 145
//if type is Dictionary<string, string>
var mapKey = Serializer.UnescapeString(keyValue);
var mapValue = Serializer.UnescapeString(elementValue);
That's why:
var a = JsonSerializer.DeserializeFromString<Dictionary<string, string>>():
//returns <"key", "[{"> incorrect value
var b = JsonSerializer.DeserializeFromString<JsonObject>();
//returns <"key","[{...}]"> correct value
JsonObject is inherited from Dictionary<string, string>
, but it is assigned a different meaning than a normal Dictionary<string, string>
to have special treatment. To me 'a' and 'b' should return the same answer, either both works, or both don't work. Now 'a' is broken and 'b' works, I personally think this is a logical error.
-
It's parsed differently by design,
Dictionary<string,string>
is expecting JSON string values which get un-escaped, whilstJsonObject
assumes that you want to dynamically parse JSON so it doesn't attempt to un-escape the raw value as a JSON string - letting you further dynamically parse the JSON object graph.mythz– mythz2013年10月28日 03:17:15 +00:00Commented Oct 28, 2013 at 3:17
I would ask myself why the second call is allowed at all.
For Dictionary<string, string>
I would expect a JSON string to look like { "key1": "val1", ...}
but it is { "key1": not a string, ...}
instead. I would expect it to fail (or return null) because of invalid or unexpected JSON format.
-
Hmm, your answer didn't cover it... JsonObject is Dictionary<string, string>, right? and JsonObject.Parse(string json) { return JsonSerializer.DeserializeFromString<JsonObject>(json);} from SS source code, right? why does that work?Tom– Tom2013年10月27日 21:58:12 +00:00Commented Oct 27, 2013 at 21:58
-
@Tom Sorry, I missed that you're using the ServiceStack implementation. Usually a JsonObject implements something like IDictionary<string, JsonValue>. I think they got reasons for their decision (maybe my answer reflects that... maybe). That's something you should ask the actual developers.Knickedi– Knickedi2013年10月27日 23:16:24 +00:00Commented Oct 27, 2013 at 23:16
-
np thanks for trying :) I found out the reason, thinking how to deal with it. Please see my answer aboveTom– Tom2013年10月27日 23:19:06 +00:00Commented Oct 27, 2013 at 23:19
-
I see that you're getting different results there, but I think that decision for this was made on purpose. JsonObject != string Dictionary (it's just misleading that JsonObject extends that dictionary). I could try to explain my assumption in my answer why they decided so (and why I agree) but I think the actual developers know better...Knickedi– Knickedi2013年10月27日 23:30:22 +00:00Commented Oct 27, 2013 at 23:30
-
1my libraries were 6+ months old, I "update all" nuget and it fixed the problem, now 'a' and 'b' both worksTom– Tom2013年10月28日 00:03:49 +00:00Commented Oct 28, 2013 at 0:03