CodeGym /Courses /C# SELF /Diving into Newtonsoft.Jso...

Diving into Newtonsoft.Json

C# SELF
Level 47 , Lesson 2
Available

1. Introduction

If you're just starting to learn about serialization in .NET, it's natural to ask: why another library when there's already the built-in System.Text.Json? The answer is simple: Newtonsoft.Json showed up earlier and over the years evolved into still one of the most flexible JSON tools in .NET.

It became the de-facto standard because it supports complex scenarios: custom contracts, powerful converters, serialization of private fields, LINQ to JSON, dynamic objects (JObject), flexible handling of cyclic references and many date/time formats. Many libraries and APIs still use Json.NET "under the hood".

Important: in some scenarios the built-in System.Text.Json is still behind the capabilities of Newtonsoft.Json, so learning Json.NET remains relevant.

How to add Newtonsoft.Json (Json.NET)

Install the package via NuGet:

dotnet add package Newtonsoft.Json

Include the namespace:

using Newtonsoft.Json;

2. Serialization with Newtonsoft.Json

Let's take the usual class Person:

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

Serialize an object to a JSON string

Person person = new Person { Name = "Ivan", Age = 30 };

// Serialize to JSON
string json = JsonConvert.SerializeObject(person);

Console.WriteLine(json);
// Output: {"Name":"Ivan","Age":30}

Deserialize JSON back to an object

string json = "{\"Name\":\"Ivan\",\"Age\":30}";

Person person = JsonConvert.DeserializeObject<Person>(json);

Console.WriteLine($"{person.Name}, {person.Age}");
// Output: Ivan, 30

What happens "under the hood"?

Newtonsoft.Json goes through all public properties (public), serializes them to JSON and writes them to a string. On deserialization it maps keys from JSON to property names and fills the object.

3. Serialization of object collections

Serializing collections and arrays

Collections work "out of the box".

List<Person> people = new List<Person>
{
    new Person { Name = "Ivan", Age = 30 },
    new Person { Name = "Maria", Age = 25 }
};

string json = JsonConvert.SerializeObject(people);
// Output: [{"Name":"Ivan","Age":30},{"Name":"Maria","Age":25}]

List<Person> deserialized = JsonConvert.DeserializeObject<List<Person>>(json);
// Now you have a list of Person again!

Features of serializing and deserializing dictionaries

var dict = new Dictionary<string, int>
{
    ["apple"] = 2,
    ["banana"] = 5
};

string json = JsonConvert.SerializeObject(dict);
// Output: {"apple":2,"banana":5}

var deserializedDict = JsonConvert.DeserializeObject<Dictionary<string,int>>(json);
// Everything works!

If keys are not strings (for example, Dictionary<int,string>), Json.NET converts keys to strings when serializing, and on deserialization it will try to convert them back. For complex keys (for example, Guid) it's safer to use Dictionary<string, TValue>.

4. Working with nested objects and hierarchies

public class Order
{
    public int Id { get; set; }
    public Person Customer { get; set; }
    public List<Product> Products { get; set; }
}
public class Product
{
    public string Title { get; set; }
    public double Price { get; set; }
}
Order order = new Order
{
    Id = 123,
    Customer = new Person { Name = "Ivan", Age = 30 },
    Products = new List<Product>
    {
        new Product { Title = "Laptop", Price = 50000.0 },
        new Product { Title = "Mouse", Price = 1500.0 }
    }
};

string json = JsonConvert.SerializeObject(order);

Console.WriteLine(json);

Result: nested objects will be correctly represented inside the JSON structure.

5. Configuring serialization with attributes

Ignore a property

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

    [JsonIgnore]
    public int Age { get; set; }
}

Now Age will not appear in the JSON.

Rename a property

public class Person
{
    [JsonProperty("full_name")]
    public string Name { get; set; }
}

In JSON the name will be "full_name".

6. Flexible configuration: JsonSerializerSettings

Formatting (pretty multi-line JSON):

string json = JsonConvert.SerializeObject(
    people,
    Formatting.Indented
);

Result:

[
  {
    "Name": "Ivan",
    "Age": 30
  },
  {
    "Name": "Maria",
    "Age": 25
  }
]

Commonly used settings:

Property Description
NullValueHandling
How to handle null properties (skip them or write explicit null)
DefaultValueHandling
Whether to skip default values
ReferenceLoopHandling
What to do with reference loops
DateFormatString
Format string for dates and times

Example that skips null:

string json = JsonConvert.SerializeObject(
    person,
    new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }
);

7. Working with dynamic JSON structures: JObject, JArray and others

When the JSON structure is unknown upfront, use types from Newtonsoft.Json.Linq:

using Newtonsoft.Json.Linq;

string json = @"{
    'Name': 'Ivan',
    'Age': 30,
    'Skills': ['C#', 'SQL', 'JSON']
}";

JObject obj = JObject.Parse(json);

Console.WriteLine(obj["Name"]);     // Ivan
Console.WriteLine(obj["Skills"][0]); // C#

Creating JSON "on the fly":

var jObj = new JObject
{
    ["Status"] = "Success",
    ["Result"] = new JArray("item1", "item2", "item3")
};

Console.WriteLine(jObj.ToString(Formatting.Indented));

JObject and JArray are representations of a JSON object and array — basically convenient collections.

8. Useful nuances

Cyclic references

Newtonsoft.Json can handle them flexibly:

var settings = new JsonSerializerSettings
{
    ReferenceLoopHandling = ReferenceLoopHandling.Ignore
};

string json = JsonConvert.SerializeObject(obj, settings);

This way loops will be skipped. To preserve references you can use ReferenceLoopHandling.Serialize together with [JsonObject(IsReference = true)].

Serializing anonymous and dynamic objects

var anon = new { Foo = 42, Bar = "Hello" };
string json = JsonConvert.SerializeObject(anon);
// {"Foo":42,"Bar":"Hello"}

Validation and error handling

try
{
    Person p = JsonConvert.DeserializeObject<Person>(brokenJson);
}
catch (JsonSerializationException ex)
{
    Console.WriteLine("Error during deserialization: " + ex.Message);
}

Comparison: Newtonsoft.Json vs System.Text.Json

Newtonsoft.Json (Json.NET) System.Text.Json (.NET)
Supported .NET .NET Framework/Standard/6+ .NET Core 3.0+ / .NET 5/6/9
LINQ to JSON (JObject/JArray) Yes No
Flexible configuration Very large Limited
Attributes ([JsonProperty], ...) Yes Yes (partially, fewer capabilities)
Support for private properties Yes No
Speed Slower in some scenarios Faster
Complex converters Yes Yes (less flexible for now)
Support for DataTable, DataSet Yes No
Documentation and examples Lots Growing

9. Beginner mistakes and common pitfalls

Mistake #1: properties become null after deserialization.
Often a property has no setter or there's no parameterless constructor — the serializer has nothing to populate the object with.

Mistake #2: property names mismatch between JSON and the class.
If JSON field is "fullName" but the class has FullName, use [JsonProperty] or configure a ContractResolver to map names.

Mistake #3: serialization only works with public properties by default.
Private fields/properties are not serialized without extra settings. You need converters or special resolvers/contracts.

Mistake #4: cyclic references lead to StackOverflowException.
Mutual object references can loop serialization without settings. Configure reference handling (for example, ReferenceLoopHandling) or change the data model.

2
Task
C# SELF, level 47, lesson 2
Locked
Working with Nested Structures
Working with Nested Structures
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION