1

Given the following simple class:

public class Person
{
  public int id { get; set; }
  public List<Order> orders { get; set; }
}

When the orders property is null, and once the Person instance is serialized using JSON.NET below:

var json = JsonConvert.SerializeObject(myPerson);

I need the physical output returned (it's an existing constraint) to look like the following when orders = null:

{
 "id": 1,
 "orders": []
}

However, what is happening is that the orders property is being returned with all null values like below:

{
 "id": 1,
 "orders": [
    {
      "id": null,
      "total":null,
      "orderDate":null,
      "itemQuantity":null
    }
  ]
}

I can't have that collection be returned if null but rather it needs to show as basically an empty array like: "orders": []"

I've tried:

myPerson.orders = null;

However, this still produces the full object collection being displayed with all null values.

How can I intervene on the serialization or manipulation of this object so I can have it physically return as an empty array as opposed to an expanded null collection of fields?

EDIT: A portion of the question was answered via the comments. The full blown object instance being returned was due to a LINQ query returning a resultset that instantiated a default instance OF orders. However the main part of the question is still about making it return "orders":[] and not "orders":null

atconway
  • 20,624
  • 30
  • 159
  • 229
  • 2
    Somewhere in your code you are allocating a default `Order` and adding it to the list -- possibly in some converter or default constructor. What does the default constructor for `Person` look like? – dbc Aug 20 '15 at 19:29
  • @dbc - Yes this is exactly what I'm trying to search down now. The constructor for Person isn't defined its just a default empty constructor. As you say I think a default instance is being added. Regardless, even if I find it, I think `null` would be returned for the property as a whole and I still need `[]` – atconway Aug 20 '15 at 19:34
  • `JsonConvert.SerializeObject(new Person() { id = 1, orders = null })` gives me `{"id":1,"orders":null}`. – poke Aug 20 '15 at 19:36
  • @poke @dbc - OK the 1st half of the question is answered. Obviously for the sake of brevity I had to omit some details for the question. My code was inadvertently adding a default instance upon taking the results of a LINQ query. So now I have `"orders":null` However, I still need to make it be `"orders":[]` Should I go brute force and find/replace after serialization or is there a serializer setting/attribute that can do this? – atconway Aug 20 '15 at 19:42
  • 2
    If you do `person.orders = new List()` then it should be an empty array instead of `null`. – poke Aug 20 '15 at 19:44
  • @poke - That did it! If you want to compose an answer about there being a default instance causing the initial behavior _combined_ with how to properly instantiate it, I'll mark it as the answer. – atconway Aug 20 '15 at 19:49

2 Answers2

1
"orders": [
  {
    "id": null,
    "total":null,
    "orderDate":null,
    "itemQuantity":null
  }
]

The output you see above cannot be caused by an empty orders property of the person. The JSON array does have an item, so there needs to be an item in the orders list too. It just happens to have the default value for all its properties which is why there is a null for every key.

So if you figure out where that empty Order object is being created and added to the list, you can get rid of that output.

As for serializing an empty list, you have two options: You can either serialize it as null by setting the property to null directly (person.orders = null). Or you can serialize it as an empty array [] by assigning an empty list (person.orders = new List<Order>()) to the property.

You can also manipulate the serializer to always create an empty array even if the property is null. See this answer for an example.

Community
  • 1
  • 1
poke
  • 369,085
  • 72
  • 557
  • 602
0

You can initialize the collection in the class constructor, and then you will get your desired output:

public class Person
{
    public Person()
    {
        orders = new List<Order>();
    }

    public int id { get; set; }
    public List<Order> orders { get; set; }
}

Also, you can personalize the getter for your property, but personally I don't recommend it because it can be hard to find in case of errors.

public class Person
{       
    public int id { get; set; }

    private List<Order> _orders;

    public List<Order> orders
    {
        get
        {
            if (_orders == null)
            {
                _orders = new List<Order>();
            }

            return _orders;
        }
        set { _orders = value; }
    }
}
Hernan Guzman
  • 1,235
  • 8
  • 14