CodeGym /Courses /C# SELF /Controlling serialization of collections

Controlling serialization of collections

C# SELF
Level 46 , Lesson 4
Available

1. Introduction

As much as we'd like to think collections serialize and deserialize perfectly "out of the box", in real projects that's often not the case. Sometimes you need to hide certain collections from serialization — for example, internal cached data. Sometimes you need to rename collection properties so they match the API contract. In some cases it's important to control which elements are saved or ignored, or even transform a collection in a special way so the resulting JSON looks clear and "readable" to other services.

Luckily, System.Text.Json offers a simple and transparent way to control serialization using attributes that can be applied to collections and individual elements. In this section we'll continue developing our library model to see how this works in practice.

2. Excluding collection properties: [JsonIgnore]

Let's start with something simple. Sometimes your class has a collection that must not be serialized — for example, temporary, cached or sensitive data. What to do? Of course, [JsonIgnore]!

Imagine we have a class Library where we added a property List<Book> Cache, used only for quick access:

using System.Text.Json.Serialization;

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

    public List<Book> Books { get; set; }

    [JsonIgnore]
    public List<Book> Cache { get; set; } // Not serialized!
}
// Usage example:
var library = new Library
{
    Name = "Main Library",
    Books = new List<Book>
    {
        new Book { Title = "The Magic Valley", Author = new Author { Name = "Tove Jansson", BirthYear = 1914 } }
    },
    Cache = new List<Book>
    {
        new Book { Title = "Lord of the Flies", Author = new Author { Name = "William Golding", BirthYear = 1911 } }
    }
};

string json = JsonSerializer.Serialize(library, new JsonSerializerOptions { WriteIndented = true });
Console.WriteLine(json); // The JSON doesn't contain the Cache property!

The serialization result will look roughly like this:

{
  "Name": "Main Library",
  "Books": [
    {
      "Title": "The Magic Valley",
      "Author": {
        "Name": "Tove Jansson",
        "BirthYear": 1914
      }
    }
  ]
}

See? No "caches" exposed to the outside world. Anything marked with [JsonIgnore] is hidden and safe, like the Wi‑Fi password in your head.

3. Renaming collections with [JsonPropertyName]

Do you often work with APIs that expect, say, "items" instead of "Books"? Or maybe you don't want to rename the C# field (to avoid confusion), but in JSON it should "sound" different?

Here's how to do it:

using System.Text.Json.Serialization;

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

    [JsonPropertyName("items")]
    public List<Book> Books { get; set; }

    [JsonIgnore]
    public List<Book> Cache { get; set; }
}
// Serialization:
var library = new Library { Name = "Branch #1", Books = new List<Book>() };
string json = JsonSerializer.Serialize(library, new JsonSerializerOptions { WriteIndented = true });
Console.WriteLine(json);

Output:

{
  "Name": "Branch #1",
  "items": []
}

Note that deserialization will also correctly map the items field from JSON back to Books in C# — the magic works both ways.

4. Controlling serialization of collections and their elements

For this you'll need JsonIgnoreCondition.WhenWritingNull and/or nullable types.

Sometimes a collection is simply an optional field. For example, a newly created library may not have books yet. If you don't want the JSON to include the property books: null, you can control this via options:

var library = new Library { Name = "Empty Library" };
// Books is not initialized = null

var options = new JsonSerializerOptions
{
    DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
    WriteIndented = true
};

string json = JsonSerializer.Serialize(library, options);
Console.WriteLine(json);

Result:

{
  "Name": "Empty Library"
}

If you have an empty list (but not null), the serializer will produce "books": []. This distinction is important because sometimes you intentionally want to hide a field if it's null, but not if it's an empty list.

5. [JsonIgnore] attribute on element properties

Serialization attributes also work inside collection elements. You can hide individual properties on each object in the list.

public class Book
{
    public string Title { get; set; }
    public Author Author { get; set; }

    [JsonIgnore]
    public string InternalCode { get; set; }
}

Now when serializing a Book from the Books collection, the InternalCode field won't appear in the JSON.

6. Addressing collections via “indices” or nested structures

Sometimes you need to serialize collections not just as arrays but, for example, as "maps" (dictionary) — if each book has a unique identifier. In that case — without fancy per-element attributes but using standard tools — you can declare a dictionary property:

public class Library
{
    [JsonPropertyName("catalog")]
    public Dictionary<string, Book> BookCatalog { get; set; }
}

When serialized the dictionary becomes an object with key-value pairs:

var library = new Library
{
    BookCatalog = new Dictionary<string, Book>
    {
        ["978-5-699-12345-6"] = new Book { Title = "Dictionary", Author = new Author { Name = "Unknown", BirthYear = 2000 } }
    }
};

JSON:

{
  "catalog": {
    "978-5-699-12345-6": {
      "Title": "Dictionary",
      "Author": {
        "Name": "Unknown",
        "BirthYear": 2000
      }
    }
  }
}

This representation is convenient for APIs where preserving the association between key and object matters.

7. Errors and difficulties when controlling collection serialization

If you try to serialize a collection where not all elements are properly initialized (for example, the list contains null), by default System.Text.Json will write such elements as null in the array.

Even if you set DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, null elements inside an array will remain — that rule applies to object properties, not to the contents of collections. To avoid that, clean the collection beforehand: RemoveAll(b => b == null).

A common confusion during deserialization is mismatched names. If you forget to specify [JsonPropertyName], the class will expect the property Books, but you send JSON with items: as a result the collection won't be filled and will remain empty. Always double-check names!

8. Table: where main attributes apply

Attribute Can it be applied to collections? Can it be applied to collection elements? Usage examples
[JsonIgnore]
yes yes Hide a list or a field inside Book
[JsonPropertyName]
yes yes Rename Books → items or Title → name
[JsonInclude]
yes yes Include private properties in serialization
[JsonConverter]
yes yes Assign a custom converter for a list

9. Serialization schema for collections with attributes


+-------------+
|   Library   |
+-------------+
  | Name           -- serialized as "Name"
  | Books          -- [JsonPropertyName("items")], serialized as "items": [...]
  | Cache          -- [JsonIgnore], not serialized
  | BookCatalog    -- [JsonPropertyName("catalog")], serialized as "catalog": {...}
JSON result looks roughly like:
{
  "Name": "City Library",
  "items": [
    {
      "Title": "1984",
      "Author": {
        "Name": "George Orwell",
        "BirthYear": 1903
      }
    },
    {
      "Title": "Great Expectations",
      "Author": {
        "Name": "Charles Dickens",
        "BirthYear": 1812
      }
    }
  ],
  "catalog": {
    "978-1234567890": {
      "Title": "The Call of Cthulhu",
      "Author": {
        "Name": "Howard Phillips Lovecraft",
        "BirthYear": 1890
      }
    }
  }
}

10. Practical importance and interview / real-project notes

In "production" you always need to consider the external API contract and serialization requirements. You should know how to "hide" internal collections, match name casing and naming style, and even dynamically change the serialization schema depending on the client version.

Typical interview questions:

  • How to serialize only part of the data?
  • How to make a collection property not appear in JSON?
  • How to map property names between C# and JSON if they differ?
  • Is it possible to hide individual elements inside a collection from serialization (for example, confidential info)?

Answers revolve around proper use of attributes and serializer settings: [JsonIgnore], [JsonPropertyName], JsonSerializerOptions and thoughtful handling of collection contents.

2
Task
C# SELF, level 46, lesson 4
Locked
Renaming a Collection Property
Renaming a Collection Property
1
Survey/quiz
Serializing Collections, level 46, lesson 4
Unavailable
Serializing Collections
Serializing nested and hierarchical objects
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION