2

I have an invoice with two lines. On both lines I have the same product item selected. Now I want to deserialize this with Json.NET (former Newtonsoft.Json):

{
   "invoiceNumber":"SALES-001",
   "lines":[
      {
         "itemId":1,
         "lineDescription":"product with discount",
         "quantity":1,
         "price":1000,
         "item":{
            "id":1,
            "description":"product",
            "salesPrice":1200
         }
      },
      {
         "itemId":1,
         "lineDescription":"product",
         "quantity":1,
         "price":1200,
         "item":{
            "id":1,
            "description":"product",
            "salesPrice":1200
         }
      }
   ]
}

When deserializing this to C# objects I believe for each item a new instance is created, somewhat like:

new Item { Id = 1, Description = "product", SalesPrice = 1200 }

But what I actually want is that in the deserialization process the object instance for item, created on the first line, will be reused on the second line (by means of object comparison?).

Reading the docs I haven't found it. And going through the code I saw JsonSerializerSettings offers ObjectCreationHandling.Reuse and PreserveReferencesHandling.Objects. Only this does not seem to have the desired effect. So I've come to think that this is not possible by configuration.

Any suggestions would be great!

sam
  • 330
  • 2
  • 7
  • So do you need a Collection containing only distinct objects? – Boris Sokolov Mar 10 '16 at 09:57
  • Maybe I have to rephrase some, but what I want is that both lines refere to the same item instance. So that only one item is instantiated – sam Mar 10 '16 at 10:28
  • 1
    So you could parse the Json and then run Disctinct or DistinctBy over the Collection – Boris Sokolov Mar 10 '16 at 11:40
  • Thanks for the suggestion. But if I understand correctly, this means I should rebuild the graph because after deserializing I want to pass the object along N-tiers. Also doing the equality comparison before serializing it to an object seems to me more efficient. Last but not least, I'm looking for a more generic approach that would achive this for any incomming JSON containing duplicate tokens.. Maybe I should update my question ;p – sam Mar 10 '16 at 13:10
  • Possible duplicate of [JSON: Standard way of referencing an object by identity (for, eg, circular references)?](http://stackoverflow.com/questions/4001474/json-standard-way-of-referencing-an-object-by-identity-for-eg-circular-refer) – Liam Mar 18 '16 at 10:04
  • No, as my question is specifically for deserializing with Json.NET – sam Mar 18 '16 at 13:47
  • Json.NET supports [object references](http://www.newtonsoft.com/json/help/html/preserveobjectreferences.htm) – Zdeslav Vojkovic Mar 18 '16 at 14:07

1 Answers1

0

Ok, so for Json.NET you can achieve this. But the JSON graph must be changed in order to make it work.

I couldn't find a standard where this behaviour is described. Json.NET seems to reuses the object instance if you change your JSON to:

{
    "$id":1,
    "invoiceNumber":"SALES-001",
    "lines":[
        {
            "$id":2,
            "itemId":1,
            "lineDescription":"product with discount",
            "quantity":1,
            "price":1000,
            "item":{
                "$id":3,
                "id":1,
                "description":"product",
                "salesPrice":1200
            }
        },
        {
            "$id":4,
            "itemId":1,
            "lineDescription":"product",
            "quantity":1,
            "price":1200,
            "item":{
                "$ref":3
             }
        }
    ]
}

Here you can see every object gets an unique "$id" assigned. The first item gets "$id": 3 and the second item in the graph references to this "$ref": 3

I've found a project that handles the transformation of your JavaScript object: https://bitbucket.org/smithkl42/jsonnetdecycle

Quote from the project:

JsonNetDecycle

This is a very simple TypeScript/JavaScript library that can be used to re-establish object references removed by Json.NET. It's based on the cycle.js library by Douglas Crockford, but uses the non-standard reference style used by Json.NET instead of the IETF draft proposal for JSON references. Before you ask, yes, it would probably be better if Json.NET adopted the IETF proposed standard. But some of us need to get work done before that is likely to happen.

You use it kinda like this:

var room = {
    "$id": "57",
    "Name": "_default",
    "User": {
        "$id": "58",
        "UserTag": "ken",
        "Sessions": [{
            "$id": "59",
            "SessionId": "0ca7474e-273c-4eb2-a0c1-1eba2f1a711c",
            "User": {
                "$ref": "58"
            },
            "Room": {
                "$ref": "57"
            }
        }],
    },

    "Sessions": [{
        "$ref": "59"
    }]
};
JsonNetDecycle.retrocycle(room);
alert(room.Sessions[0].User.UserTag);
Community
  • 1
  • 1
sam
  • 330
  • 2
  • 7
  • I don't understand this answer. You talk about a new property but you don't explain how you use this or why you need it very well. Basically you seem to be saying the answer is add this new property, but I fail to see how adding a new property into a javascript object builds object references? – Liam Mar 18 '16 at 09:57
  • Right, so, TL;DR: you're using [Json refs](http://stackoverflow.com/questions/17595377/json-schema-regarding-use-of-ref). – Liam Mar 18 '16 at 10:02
  • [This](http://stackoverflow.com/a/31725765/542251) seems to suggest that this isn't particularly well supported. [The document](https://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03) this is based on and is mentioned in that blog appears to be an expired draft. – Liam Mar 18 '16 at 10:05
  • 1
    Thanks for comfirming that this is not really well supported in general. I'll quote some of the project I'm linking to clearify. – sam Mar 18 '16 at 13:52