0

I have a dictionary property I want to serialize with a reference type as its key. Since JSON.NET only supports primitive types as keys, I set my dictionary type to [JsonArray]. However, now all my dictionary keys are being duplicated when they are referenced more than once, causing an error on deserialization saying that there are duplicate $id values. How do I make JSON.NET actually create references in this case, as it does in all other cases, instead of duplicating the objects each time they occur? Could this have something to do with the fact that KeyValuePair is a value type?

ekolis
  • 6,270
  • 12
  • 50
  • 101
  • Newtonsoft by default will return object with $id starting from 1. So perhaps you are asking data 2 times, maybe different types of request, but for each request newtonsoft generates new id starting from 1. So you should use containers maybe – Medet Tleukabiluly Sep 09 '14 at 03:41

3 Answers3

0

Have you added

PreserveReferencesHandling = PreserveReferencesHandling.Objects

to your JsonSerializerSettings? See the documentation on preserving object references for more information.

Also, note that types that implement ISerializable do not work properly with preserved object references; if your reference key type implements ISerializable then you'll need to do something else, such as adding attributes or a JsonConverter to control its serialization.

Jeffrey Hantin
  • 35,734
  • 7
  • 75
  • 94
  • I have PreserveReferencesHandling set to All. None of the classes I'm trying to serialize implement ISerializable, though some of them have the [Serializable] attribute. Also, the sub-objects of my key objects are referenced properly; it's just the keys themselves that are duplicated. – ekolis Jan 31 '14 at 18:26
  • I tried changing PreserveReferencesHandling from All to Objects, it it didn't help. – ekolis Jan 31 '14 at 18:30
  • @ekolis Is the dictionary getting pre-populated in the parent object's constructor? JSON.Net calls the default constructor and won't clear pre-existing items from the list, which can introduce apparent duplicates. – Jeffrey Hantin Feb 01 '14 at 02:08
  • No, I think you might be misunderstanding. I'm not saying that when I deserialize the data, I get duplicate objects. I'm saying that when I deserialize the data, JSON.NET throws an exception because there are duplicate $id values in the serialized data. (Hmm, I wonder why when I try to @ your username here, it disappears when I save the comment?) – ekolis Feb 01 '14 at 21:33
  • 1
    @ekolis, if it's in reply to my answer then @ me is implied so redundant. In any case, I think you've just run across a "blind spot" in JSON.NET here; it's really more akin to `XmlSerializer` than `BinaryFormatter`, and its support for reference aliasing is very incomplete and tends to break if you do anything remotely interesting. – Jeffrey Hantin Feb 01 '14 at 23:24
  • Oh, OK. Yeah, that's probably why I went with custom serialization in the first place; I'm trying to switch back to JSON.NET due to another issue I posted with assembly versioning. – ekolis Feb 03 '14 at 19:43
0

NOTE: This will completely remove the $id properties!

For me and many other the PreserveReferencesHandling setting doesn't work.

This answer did work though: Json.Net adding $id to EF objects despite setting PreserveReferencesHandling to "None"

In your implementation of DefaultContractResolver/IContractResolver, add this;

public override JsonContract ResolveContract(Type type) {
    var contract = base.ResolveContract(type);
    contract.IsReference = false;
    return contract;
}
Community
  • 1
  • 1
Howie
  • 2,760
  • 6
  • 32
  • 60
  • That doesn't make sense to me. I don't want to get rid of the IDs and the whole reference system; I want to keep the references, so I (in theory) don't get duplicate objects, but still not get duplicate objects in practice too! – ekolis Feb 10 '14 at 20:27
  • I see. I guess I misunderstood your question, sorry! – Howie Feb 11 '14 at 07:10
0

I filed a bug report with JSON.NET for this, and the answer I got was to use ObjectCreationHandling.Replace.

ekolis
  • 6,270
  • 12
  • 50
  • 101