Search code examples
c#jsonserializationjson.net

How do I serialize (JSON) an object/class but not its children


I have:

public Class City
{
    public long ID { get; set }
    ...
    public State State { get; set; }
    ...
}
public Class State
{
    public long ID { get; set; }
    ...
    public Country { get; set; }
    ...
}
public Class Country 
{
   public long ID {get; set;}
   ...
}

in my code I serialize a list<Country> and list<State>, etc... The problem is if I serialize my list of Cities I get something like this:

{
  "ID": 3119841,
  "Name": "A Coruna",
  ...
  "State": {
    "ID": 3336902,
    "Name": "Galicia",
    "Country": {
      "ID": 2510769,
      "Name": "Spain",
      ...
      }
    ...
  }
  ...
}

this cause memory and performance issues when deserializing due to having thousands of copies of the same country object and state object, etc... what I would like to generate is:

{
  "ID": 3119841,
  "Name": "A Coruna",
  ...
  "StateID": 3336902,
  ...
}

and then I will link up the city to the states (which I will have linked up to the country, etc.) If I use the Ignore flag (JsonIgnoreAttribute) on the fields in the state and country classes, then I will not be able to Serialize them (I think)...

How do I achieve what I am after? (I am currently using Json.NET, but am happy to use anything that will accomplish the goal.)


Solution

  • To exclude a child structure from being serialized, you can use the [JsonIgnore] attribute:

    public class City
    {
        public long ID { get; set }
        ...
        [JsonIgnore]
        public State State { get; set; }
        ...
    }
    

    If you want to flatten the structure, things become more complex. Your options are:

    1. Create an intermediate flattened structure, as the result of e.g. a Linq projection.
    2. Create a custom contract resolver for your structure, an example that may provide some inspiration on how to achieve this can be found in this question: How to flatten a referenced object into two json.net properties on the referer?
    3. Expose the additional properties of your State class that you want to "flatten" in the City class as properties:
        public long StateID { get { return State.ID; } }

    Note that some frameworks will also require you to add the [ScriptIgnore] and/or [NonSerialized] attributes, in addition to or as alternatives of the [JsonIgnore].