JSON.NET does not serialize public properties if object inherits from Dictionary<,>

5,868 views
Skip to first unread message

georgiosd

unread,
Jan 10, 2013, 2:43:13 AM1/10/13
to rav...@googlegroups.com
I guess this is not a very common use case but I thought people here may like to know as it will affect their Raven serialization 

Quite surprised to find that serializing this type, results in empty JSON "{}"

void Main()
{
JsonConvert.SerializeObject(new Foo { Id = "5" }).Dump();
}

class Foo : Dictionary
{
public string Id { get; set;}
}


I created an issue about this but was resolved as "Not a bug". Thoughts?

http://json.codeplex.com/workitem/23769


Fitzchak Yitzchaki

unread,
Jan 10, 2013, 5:21:46 AM1/10/13
to <ravendb@googlegroups.com>
Dictionary does not have any json equivalent, so there is no way to actually serialize this to json, this why it's not a bug.

Georgios Diamantopoulos

unread,
Jan 10, 2013, 5:38:17 AM1/10/13
to rav...@googlegroups.com
That's not correct. 

JsonConvert.SerializeObject(new Dictionary<string, string> { { "foo", "bar" }} , Newtonsoft.Json.Formatting.Indented).Dump();

Gives

{
"foo": "bar"
}

The problem, I assume, is that JSON.NET detects it's a dictionary and ONLY serializes the pairs exposed from the dictionary's enumerator.



Date: Thu, 10 Jan 2013 12:21:46 +0200
Subject: Re: [RavenDB] JSON.NET does not serialize public properties if object inherits from Dictionary<,>
From: fitz...@hibernatingrhinos.com
To: rav...@googlegroups.com

Matt Johnson

unread,
Jan 10, 2013, 10:19:36 AM1/10/13
to ravendb
The reason it's not common is because of DDD guidelines about entities
and value objects.

One would never create a document in raven with:
public class Foo : Dictionary
{
public string Id { get; set; }
}

Instead they would do this:
public class Foo
{
public string Id { get; set; }
public Dictionary Bar { get; set; }
}

Which works just fine.

On Jan 10, 3:38 am, Georgios Diamantopoulos <georgi...@live.com>
wrote:
> That's not correct.
> JsonConvert.SerializeObject(new Dictionary<string, string> { { "foo", "bar" }} , Newtonsoft.Json.Formatting.Indented).Dump();
> Gives
> {
>   "foo": "bar"}
>
> The problem, I assume, is that JSON.NET detects it's a dictionary and ONLY serializes the pairs exposed from the dictionary's enumerator.
>
> Date: Thu, 10 Jan 2013 12:21:46 +0200
> Subject: Re: [RavenDB] JSON.NET does not serialize public properties if object inherits from Dictionary<,>
> From: fitzc...@hibernatingrhinos.com
> To: rav...@googlegroups.com
>
> Dictionary does not have any json equivalent, so there is no way to actually serialize this to json, this why it's not a bug.
>

Georgios Diamantopoulos

unread,
Jan 10, 2013, 10:35:22 AM1/10/13
to rav...@googlegroups.com
Forgive my limited DDD exposure but, isn't it valid to have an ExtendedDictionary which has more public properties?
If not, please recommend a good DDD book :)


> Date: Thu, 10 Jan 2013 07:19:36 -0800
> Subject: [RavenDB] Re: JSON.NET does not serialize public properties if object inherits from Dictionary<,>
> From: mj1...@hotmail.com
> To: rav...@googlegroups.com

Matt Johnson

unread,
Jan 10, 2013, 8:03:42 PM1/10/13
to ravendb
Yes, but a dictionary would still be considered a value object, even
if you extended it.

I supposed that's one reason why raven documents are implemented using
RavenJObject (an imported JObject from json.net) instead of
dictionaries.

The definitive book on DDD is from Eric Evans: http://amzn.com/0321125215.
It is a long read, and the good parts (like bounded contexts) are
towards the end. And it's based in Java. I am on the lookout for a
newer, smaller, more focused, C# based DDD book - if anyone can
recommend one.


On Jan 10, 8:35 am, Georgios Diamantopoulos <georgi...@live.com>
wrote:
> Forgive my limited DDD exposure but, isn't it valid to have an ExtendedDictionary which has more public properties?If not, please recommend a good DDD book :)

Georgios Diamantopoulos

unread,
Jan 11, 2013, 3:18:43 AM1/11/13
to rav...@googlegroups.com
Thanks for the book ref. Did Java back in the day so I should be able to cope with the lower camel-case convention which I find extra-irritating to the eyes :)

I don't really get how this is important in the case of JSON.NET but I guess I should come back after I've read the book!



> Date: Thu, 10 Jan 2013 17:03:42 -0800

Matt Johnson

unread,
Jan 11, 2013, 12:03:24 PM1/11/13
to ravendb
The json stuff is not related to DDD. you proably won't find anything
about json in that book. :)

The DDD concern is that Dictionary is a Value Object. You don't
create an Entity by extending a VO. Entities *encapsulate* Value
Objects. In RavenDB terms - the dictionary would go inside the
Document. The document isn't a dictionary itself. In OOP terms, the
relationship is "has a" instead of "is a".

Going back to the JSON issue. Say you wanted to extend a dictionary
and actually use it as a VO. So not adding an Id property, but some
other property like Name. Even then, you have issues.
Why? Because Dictionary<T,T> implements the ISerializable interface so
that the values being serialized are coming from the key/value pairs
of the dictionary. Json.Net honors that interface.

It wouldn't really make sense anyway. Say you had:

public class Foo : Dictionary<string,string>
{
public string Name { get; set; }
}

And then you had json of:

foo
{
"Name" : "fred",
"Bar" : "baz"
}

How would deserialization know where to put the name? In a normal
dictionary, both items would go into the key/value pairs. What
happens in this one? Does Name go in the property instead of the
dictionary? Does it go in both? Do I have to synchronize them
somehow? It just doesn't work.

Now, you certainly could add some properties that poked into the
dictionary directly:

public class Foo : Dictionary<string,string>
{
public string Name
{
get { return this["Name"]; }
set { this["Name"] = value; }
}
}

On Jan 11, 1:18 am, Georgios Diamantopoulos <georgi...@live.com>

fschwiet

unread,
Jan 11, 2013, 2:18:13 PM1/11/13
to rav...@googlegroups.com
Maybe a more succinct example that shows there isn't a good general solution is


    class Foo : Dictionary
    {
        public string Id { get; set;}
    }

    var f = new Foo();
    f.Id = "hello"
    f["Id"] = "world";

Georgios Diamantopoulos

unread,
Jan 13, 2013, 11:32:33 AM1/13/13
to rav...@googlegroups.com
That certainly explains it, thank you for taking the time to write it :)

PS: i won't be too disappointed if i buy the book and not find any json stuff in it!

Sent from my iPad

georgiosd

unread,
Jan 18, 2013, 3:12:32 AM1/18/13
to rav...@googlegroups.com
Don't know if they're any good but I've found these:

Jimmy Nilsson, «Applying Domain-Driven Design and Patterns: With Examples in C# and .NET»
Addison Wesley | ISBN: 0321268202 | 2006

.NET Domain-Driven Design with C#: Problem - Design - Solution
432 pages | Wrox (April 28, 2008) |

This SO post seems to highlight the differences between the three:

http://stackoverflow.com/questions/80742/net-domain-driven-design-with-c-sharp
Reply all
Reply to author
Forward
0 new messages