
{"id":2064,"date":"2016-07-25T17:45:46","date_gmt":"2016-07-25T21:45:46","guid":{"rendered":"http:\/\/www.ikriv.com\/blog\/?p=2064"},"modified":"2016-07-25T17:45:46","modified_gmt":"2016-07-25T21:45:46","slug":"json-net-and-dictionaries","status":"publish","type":"post","link":"https:\/\/ikriv.com\/blog\/?p=2064","title":{"rendered":"Json.NET and dictionaries"},"content":{"rendered":"<p>TL;DR Json.NET can serialize and deserialize dictionaries with simple keys like integers or strings. It can serialize, but not deserialize dictionaries with more complex keys.<\/p>\n<p>Longer version: Json.NET uses ToString() to convert a dictionary key to JSON field identifier. A simple case works like this:<\/p>\n<p><!--more--><\/p>\n<p><code><\/p>\n<pre>            var dict = new Dictionary&lt;int, string&gt;\n            {\n                {10, \"ten\"},\n                {42, \"forty two\"}\n            };\n\n            var json = JsonConvert.SerializeObject(dict);\n            Console.WriteLine(json); \/\/ prints {\"10\":\"ten\",\"42\":\"forty two\"}\n\n            var deserialized = JsonConvert.DeserializeObject&lt;Dictionary&lt;int, string&gt;&gt;(json); \/\/ gets your dictionary back<\/pre>\n<p><\/code><\/p>\n<p>The dictionary value can be of any complex type: normal serialization rules apply.<\/p>\n<p><code><\/p>\n<pre>            var dict = new Dictionary&lt;int, Tuple&lt;int, string&gt;&gt;()\n            {\n                {10, Tuple.Create(10, \"ten\")},\n                {42, Tuple.Create(42, \"forty two\")},\n            };\n\n            Console.WriteLine();\n            var json = JsonConvert.SerializeObject(dict);\n            Console.WriteLine(json); \/\/ {\"10\":{\"Item1\":10,\"Item2\":\"ten\"},\"42\":{\"Item1\":42,\"Item2\":\"forty two\"}}\n\n            var deserialized = JsonConvert.DeserializeObject&lt;Dictionary&lt;int, Tuple&lt;int, string&gt;&gt;&gt;(json);<\/pre>\n<p><\/code><\/p>\n<p>However, Json.NET uses <code>ToString()<\/code> to generate dictionary keys:<\/p>\n<p><code><\/p>\n<pre>            var dict = new Dictionary&lt;Tuple&lt;int, int&gt;, string&gt;\n            {\n                { Tuple.Create(10,20), \"ten-twenty\" },\n                { Tuple.Create(5,3), \"five-three\" },\n            };\n\n            var json = JsonConvert.SerializeObject(dict);\n            Console.WriteLine(json); \/\/ {\"(10, 20)\":\"ten-twenty\",\"(5, 3)\":\"five-three\"}\n\n            var deserialized = JsonConvert.DeserializeObject&lt;Dictionary&lt;Tuple&lt;int, int&gt;, string&gt;&gt;(json); \/\/ blows up <\/pre>\n<p><\/code><\/p>\n<p>It is even possible to trick Json.NET into generating duplicate keys (which appears to be <a href=\"http:\/\/stackoverflow.com\/questions\/21832701\/does-json-syntax-allow-duplicate-keys-in-an-object\">technically valid JSON<\/a>):<\/p>\n<p><code><\/p>\n<pre>        struct CustomKey\n        {\n            private readonly int _val;\n\n            public CustomKey(int val)\n            {\n                _val = val;\n            }\n\n            public override string ToString()\n            {\n                return \"CustomKey\";\n            }\n\n            public override int GetHashCode()\n            {\n                return _val.GetHashCode();\n            }\n\n            public override bool Equals(object obj)\n            {\n                if (!(obj is CustomKey)) return false;\n                return _val == ((CustomKey)obj)._val;\n            }\n        }\n\n            var dict = new Dictionary&lt;CustomKey, string&gt;\n            {\n                {new CustomKey(10), \"ten\"},\n                {new CustomKey(42), \"forty two\"}\n            };\n\n            var json = JsonConvert.SerializeObject(dict);\n            Console.WriteLine(json); \/\/ {\"CustomKey\":\"ten\",\"CustomKey\":\"forty two\"}\n\n            var deserialized = JsonConvert.DeserializeObject&lt;Dictionary&lt;CustomKey, string&gt;&gt;(json); \/\/ blows up<\/pre>\n<p><\/code><\/p>\n<p>Well, no one is perfect \ud83d\ude42<\/p>\n","protected":false},"excerpt":{"rendered":"<p>TL;DR Json.NET can serialize and deserialize dictionaries with simple keys like integers or strings. It can serialize, but not deserialize dictionaries with more complex keys. Longer version: Json.NET uses ToString() <a href=\"https:\/\/ikriv.com\/blog\/?p=2064\" class=\"more-link\">[&hellip;]<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"Layout":"","footnotes":""},"categories":[3],"tags":[],"class_list":["entry","author-ikriv","has-more-link","post-2064","post","type-post","status-publish","format-standard","category-dotnet"],"_links":{"self":[{"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/2064","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2064"}],"version-history":[{"count":0,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/2064\/revisions"}],"wp:attachment":[{"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2064"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2064"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2064"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}