1

I would like to know whether it is possible to serialize object when inner object has reference to root object list's item. Small example to illustrate: situation:

class Project
{
    public List<Template> Templates { get; set; }
    public List<Task> Tasks { get; set; }
}

class Template
{
    public string Name { get; set; }
}

class Task
{        
    public Template Template { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        var template2 = new Template { Name = "Temp2" };

        var project = new Project
        {
            Templates = new List<Template>
            {
                new Template {Name = "Temp1"},
                template2,
                new Template {Name = "Temp3"}
            }
        };

        var task = new Task {Template = template2};

        project.Tasks = new List<Task> {task};

        Console.WriteLine(ReferenceEquals(project.Templates[1], project.Tasks.First().Template));

        var json = JsonConvert.SerializeObject(project);

        var projectFromJson =
            JsonConvert.DeserializeObject<Project>(
                "{\"Templates\":[{\"Name\":\"Temp1\"},{\"Name\":\"Temp2\"},{\"Name\":\"Temp3\"}],\"Tasks\":[{\"Template\":{\"$ref\":\"$.Templates[[email protected] == 'Temp2']\"}}]}");

        Console.WriteLine(ReferenceEquals(projectFromJson.Templates[1], projectFromJson.Tasks.First().Template));

        Console.Read();
    }
}

So in this example I want that Task object that has property Template would be referencing template2 object in Project object Templates list. So when create it before serializing ReferenceEquals shows that both objects references are equal, but when try again after deserializing it returns false because Task object Template property is null, so that means JSON.net do not serialize it.

Now it looks like that same JSON.net JObject knows the JSONpath syntax, but it do not work on deserializing. I know that there is IReferenceResolver, but I am not sure how this one could help in my case.

So is it possible to do with JSON.net and maybe there is other serializers which allows to have JSONpath references?

1 Answer 1

1

This is what the PreserveReferencesHandling is intended for:

// ...
var settings = new JsonSerializerSettings { 
    PreserveReferencesHandling = PreserveReferencesHandling.Objects
};
var json = JsonConvert.SerializeObject(project, settings);
var projectFromJson = JsonConvert.DeserializeObject<Project>(json);
Console.WriteLine(ReferenceEquals(projectFromJson.Templates[1],
    projectFromJson.Tasks.First().Template));

// This outputs "True"

Note that Json.NET uses its own reference syntax rather than JSONpath. The JSON for your object hierarchy would look as follows:

{
  "$id": "1",
  "Templates": [
    {
      "$id": "2",
      "Name": "Temp1"
    },
    {
      "$id": "3",
      "Name": "Temp2"
    },
    {
      "$id": "4",
      "Name": "Temp3"
    }
  ],
  "Tasks": [
    {
      "$id": "5",
      "Template": {
        "$ref": "3"
      }
    }
  ]
}
Sign up to request clarification or add additional context in comments.

3 Comments

Hi Dmitry, it worked like charm thanks! One thing to note that order of objects matters if I have list of Templates after Tasks list it do not find that reference.
@Evaldas, you're welcome! I believe the object order should not matter. I tried the Templates after Tasks and got the same "True" with the following JSON: { "$id": "1", "Tasks": [ { "$id": "2", "Template": { "$id": "3", "Name": "Temp2" } } ], "Templates": [ { "$id": "4", "Name": "Temp1" }, { "$ref": "3" }, { "$id": "5", "Name": "Temp3" } ] }
I have $ref serialization problem and those helped me stackoverflow.com/a/64910995/1831734

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.