4

How to Turn a C# Object Into a JSON String in .NET?

 2 years ago
source link: https://code-maze.com/csharp-object-into-json-string-dotnet/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

How to Turn a C# Object Into a JSON String in .NET?

Publisher Logo

We value your privacy

We and our store and/or access information on a device, such as cookies and process personal data, such as unique identifiers and standard information sent by a device for personalised ads and content, ad and content measurement, and audience insights, as well as to develop and improve products.With your permission we and our partners may use precise geolocation data and identification through device scanning. You may click to consent to our and our partners’ processing as described above. Alternatively you may click to refuse to consent or access more detailed information and change your preferences before consenting.Please note that some processing of your personal data may not require your consent, but you have a right to object to such processing. Your preferences will apply to this website only. You can change your preferences at any time by returning to this site or visit our privacy policy.

How to Turn a C# Object Into a JSON String in .NET?

Posted by Code Maze | Updated Date Jul 13, 2022 | 0

Code Maze Book Collection

Want to build great APIs? Or become even better at it? Check our Ultimate ASP.NET Core Web API program and learn how to create a full production-ready ASP.NET Core API using only the latest .NET technologies. Bonus materials (Security book, Docker book, and other bonus files) are included in the Premium package!

In this article, we’re going to learn how to serialize a C# object into a JSON string using the two main JSON libraries in the .NET ecosystem. Also, we’re going to learn how to control different aspects of the serialization process.

To download the source code for this article, you can visit our GitHub repository.

Let’s start.

Serialize C# Object Into JSON Strings Using System.Text.Json

Since .NET Core 3.0, System.Text.Json is included in the framework by default. This is the official Microsoft JSON serialization and deserialization solution:

var obj = new Product
Name = "Red Apples",
Stock = 100,
DateAcquired = DateTime.Parse("2017-08-24")
var jsonString = JsonSerializer.Serialize(obj);
var obj = new Product
{
    Name = "Red Apples",
    Stock = 100,
    DateAcquired = DateTime.Parse("2017-08-24")
};

var jsonString = JsonSerializer.Serialize(obj);

Here, we see how we can use the Serialize() static method of the JsonSerializer to get the JSON string that results from an object passed as a parameter:

{"Name":"Red Apples","Stock":100,"DateAcquired":"2017-08-24T00:00:00"}
{"Name":"Red Apples","Stock":100,"DateAcquired":"2017-08-24T00:00:00"}

Using Newtonsoft Json.NET to Serialize C# Objects

In previous versions of the framework, the JSON library that came bundled with .NET was the Newtosoft Json.NET library:

var jsonString = JsonConvert.SerializeObject(obj);
var jsonString = JsonConvert.SerializeObject(obj);

Here, we turn an object into a JSON string by calling the SerializeObject() static method of the JsonConvert object.

How to Generate Pretty JSON Strings

Often, we’ll rather have indented or “pretty” JSON strings. We can easily achieve that with System.Text.Json by using the WriteIntended property of the JsonSerializerOptions object:

var options = new JsonSerializerOptions
WriteIndented = true
var jsonString = JsonSerializer.Serialize(obj, options);
var options = new JsonSerializerOptions
{
    WriteIndented = true
};

var jsonString = JsonSerializer.Serialize(obj, options);

In a similar fashion, Newtosoft has it even easier. We can include the Formatting.Indented enumerated value directly in the call to the SerializedObject() method:

var jsonString = JsonConvert.SerializeObject(obj, Formatting.Indented);
var jsonString = JsonConvert.SerializeObject(obj, Formatting.Indented);

In both cases we will obtain a properly formatted JSON string: 

"Name": "Red Apples",
"Stock": 100,
"DateAcquired": "2017-08-24T00:00:00"
{
  "Name": "Red Apples",
  "Stock": 100,
  "DateAcquired": "2017-08-24T00:00:00"
}

Camel Case Property Names

Despite being a common formatting option, none of these libraries will format property names using camel case by default. With System.Text.Json, we need to explicitly set the PropertyNamingPolicy option in our JsonSerializerOptions object:

var options = new JsonSerializerOptions
WriteIndented = true,
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
var jsonString = JsonSerializer.Serialize(obj, options);
var options = new JsonSerializerOptions
{
    WriteIndented = true,
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase
};

var jsonString = JsonSerializer.Serialize(obj, options);

Similarly, with Newtonsoft we need to populate the ContractResolver property in our JsonSerializerSettings with an instance of the CamelCasePropertyNamesContractResolver class:

var options = new JsonSerializerSettings
Formatting = Formatting.Indented,
ContractResolver = new CamelCasePropertyNamesContractResolver()
var jsonString = JsonConvert.SerializeObject(obj, options);
var options = new JsonSerializerSettings
{
    Formatting = Formatting.Indented,
    ContractResolver = new CamelCasePropertyNamesContractResolver()
};

var jsonString = JsonConvert.SerializeObject(obj, options);

When used this way, both libraries will generate camel case JSON properties when serializing objects:

"name": "Red Apples",
"stock": 100,
"dateAcquired": "2017-08-24T00:00:00"
{
  "name": "Red Apples",
  "stock": 100,
  "dateAcquired": "2017-08-24T00:00:00"
}

How to Ignore Certain Properties When Serializing Objects

Frequently, we’ll want to prevent some of our object’s properties from showing up in the resulting JSON string.

Ignoring NULL Values in Serialization

One specific scenario is when we do not want to include the properties that contain null values. We can use JsonSerializerOptions object in System.Text.Json to set the DefaultIgnoreCondition flag:

var obj = new Product
Name = "Red Apples",
Stock = null,
DateAcquired = null
var options = new JsonSerializerOptions
WriteIndented = true,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
var jsonString = JsonSerializer.Serialize(obj, options);
var obj = new Product
{
    Name = "Red Apples",
    Stock = null,
    DateAcquired = null
};

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

var jsonString = JsonSerializer.Serialize(obj, options);

If we are using Newtonsoft, we’ll use the NullValueHandling property in JsonSerializerSettings:

var options = new JsonSerializerSettings
Formatting = Formatting.Indented,
NullValueHandling = NullValueHandling.Ignore
var jsonString = JsonConvert.SerializeObject(obj, options);
Console.WriteLine(jsonString);
var options = new JsonSerializerSettings
{
    Formatting = Formatting.Indented,
    NullValueHandling = NullValueHandling.Ignore
};

var jsonString = JsonConvert.SerializeObject(obj, options);

Console.WriteLine(jsonString);

The resulting JSON string will not include any of the null properties:

"Name": "Red Apples"
{
  "Name": "Red Apples"
}

Ignoring Specific Properties

These libraries include attributes that will let us provide serialization options on a per property basis. The most basic example of this is the JsonIgnore attribute that exists in both System.Text.Json and Newtonsoft.

We can use the attribute located in the System.Text.Json.Serialization namespace on one or more properties in our object:

public class Customer
public string Name { get; set; }
public string Address { get; set; }
[JsonIgnore]
public decimal FinancialRating { get; set; }
public class Customer
{
    public string Name { get; set; }

    public string Address { get; set; }

    [JsonIgnore]
    public decimal FinancialRating { get; set; }
}

Consequently, the resulting JSON string will not contain the FinancialRating property even though it was present in the original object:

"Name": "Pumpkins And Roses",
"Address": "158 Barfield Rd"
{
  "Name": "Pumpkins And Roses",
  "Address": "158 Barfield Rd"
}

If we are using Newtonsoft, we can achieve the same result by using the JsonIgnore attribute located in the Newtonsoft.Json namespace.

How to Serialize Anonymous and Dynamic Objects

Both libraries can handle anonymous objects correctly, out of the box:

var obj = new
FirstName = "John",
LastName = "Smith"
// System.Text.Json
var jsonStringSystem = JsonSerializer.Serialize(obj, optionsSystem);
// Newtonsoft
var jsonStringNewtonsoft = JsonConvert.SerializeObject(obj, optionsNewtonsoft);
var obj = new 
{ 
    FirstName = "John", 
    LastName = "Smith" 
};

// System.Text.Json
var jsonStringSystem = JsonSerializer.Serialize(obj, optionsSystem);

// Newtonsoft
var jsonStringNewtonsoft = JsonConvert.SerializeObject(obj, optionsNewtonsoft);
"FirstName": "John",
"LastName": "Smith"
{
  "FirstName": "John",
  "LastName": "Smith"
}

Similarly, dynamic objects work fine as well with both System.Text.Json and Newtonsoft:

dynamic dynObj = new ExpandoObject();
dynObj.Name = "Corey Richards";
dynObj.Address = "3519 Woodburn Rd";
// System.Text.Json
var jsonStringSystem = JsonSerializer.Serialize(dynObj, optionsSystem);
// Newtonsoft
var jsonStringNewtonsoft = JsonConvert.SerializeObject(dynObj, optionsNewtonsoft);
dynamic dynObj = new ExpandoObject();
dynObj.Name = "Corey Richards";
dynObj.Address = "3519 Woodburn Rd";

// System.Text.Json
var jsonStringSystem = JsonSerializer.Serialize(dynObj, optionsSystem);

// Newtonsoft
var jsonStringNewtonsoft = JsonConvert.SerializeObject(dynObj, optionsNewtonsoft);
"Name": "Corey Richards",
"Address": "3519 Woodburn Rd"
{
  "Name": "Corey Richards",
  "Address": "3519 Woodburn Rd"
}

How to Control Date and Time Format

System.Text.Json will use ISO-8601-1:2019 format when serializing DateTime or DateTimeOffset properties in our objects, like in this example: 2017-08-24T16:59:57-02:00. However, we can customize that by creating a custom converter:

public class GeneralDateTimeConverter : JsonConverter<DateTime>
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
return DateTime.ParseExact(reader.GetString() ?? string.Empty, "G", new CultureInfo("en-US"));
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
writer.WriteStringValue(value.ToString("G", new CultureInfo("en-US")));
public class GeneralDateTimeConverter : JsonConverter<DateTime>
{
    public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        return DateTime.ParseExact(reader.GetString() ?? string.Empty, "G", new CultureInfo("en-US"));
    }

    public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
    {
        writer.WriteStringValue(value.ToString("G", new CultureInfo("en-US")));
    }
}

By using this converter in our serialization code, we will get DateTime properties in general date long time format 8/24/2017 16:59:57 AM:

var options = new JsonSerializerOptions();
options.Converters.Add(new GeneralDateTimeConverter());
var obj = new
DateCreated = new DateTime(2017, 8, 24)
var jsonString = JsonSerializer.Serialize(obj, options); // {"DateCreated":"8/24/2017 12:00:00 AM"}
var options = new JsonSerializerOptions();
options.Converters.Add(new GeneralDateTimeConverter());

var obj = new
{
    DateCreated = new DateTime(2017, 8, 24)
};

var jsonString = JsonSerializer.Serialize(obj, options); // {"DateCreated":"8/24/2017 12:00:00 AM"}

Alternatively, we can apply our custom converter only to specific properties:

[JsonConverter(typeof(GeneralDateTimeConverter))]
public DateTime BirthDate { get; set; }
[JsonConverter(typeof(GeneralDateTimeConverter))]
public DateTime BirthDate { get; set; }

In Newtonsoft, using a custom date and time format is done in a very similar way. We can create our custom converter that inherits from the Newtonsoft.Json.JsonConverter abstract class:

public class GeneralDateTimeNewtonsoftConverter : JsonConverter
public override bool CanConvert(Type objectType)
return objectType == typeof(DateTime);
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
var dataString = reader.Value as string;
return DateTime.ParseExact(dataString ?? string.Empty, "G", new CultureInfo("en-US"));
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
var dateTimeValue = value as DateTime?;
writer.WriteValue(dateTimeValue?.ToString("G", new CultureInfo("en-US")));
public class GeneralDateTimeNewtonsoftConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(DateTime);
    }

    public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
    {
        var dataString = reader.Value as string;
        return DateTime.ParseExact(dataString ?? string.Empty, "G", new CultureInfo("en-US"));
    }

    public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
    {
        var dateTimeValue = value as DateTime?;
        writer.WriteValue(dateTimeValue?.ToString("G", new CultureInfo("en-US")));
    }
}

Once we have our custom converter we can use it either directly in the deserialization process:

var jsonString = JsonConvert.SerializeObject(obj, new GeneralDateTimeNewtonsoftConverter());
var jsonString = JsonConvert.SerializeObject(obj, new GeneralDateTimeNewtonsoftConverter());

Or by decorating our object’s properties with the Newtonsoft.Json.JsonConverterAttribute.

Reference Loops

To understand what a reference loop is, consider the following C# models:

public class Employee
public string FirstName { get; set; }
public string LastName { get; set; }
public Department Department { get; set; }
public class Department
public string? Name { get; set; }
public IList<Employee> Staff { get; set; } = new List<Employee>();
public class Employee
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public Department Department { get; set; }
}

public class Department
{
    public string? Name { get; set; }
    public IList<Employee> Staff { get; set; } = new List<Employee>();
}

Here, we can see how the Employee class references the Department class that, in turn, references back to the Employee class through its Staff property.

When trying to turn a circular data structure into a JSON string, we will get an error no matter if we are using System.Text.Json:

JsonException: A possible object cycle was detected.
JsonException: A possible object cycle was detected.

Or Newtonsoft:

JsonSerializationException: Self referencing loop detected with type 'Employee'. Path 'Department.Staff'.
JsonSerializationException: Self referencing loop detected with type 'Employee'. Path 'Department.Staff'.

Options for Handling Reference Loops

The best way to avoid this situation is to design our models so they do not contain reference loops. However, if that’s not possible, JSON libraries offer options to help us deal with circular references.

For System.Text.Json, we can set the JsonSerializerOptions.ReferenceHandler property to one of the ReferenceHandler enumerated value:

var employee = new Employee { FirstName = "John", LastName = "Smith" };
var department = new Department { Name = "Human Resources" };
employee.Department = department;
department.Staff.Add(employee);
var options = new JsonSerializerOptions
ReferenceHandler = ReferenceHandler.Preserve
var jsonString = JsonSerializer.Serialize(department, options);
var employee = new Employee { FirstName = "John", LastName = "Smith" };
var department = new Department { Name = "Human Resources" };
employee.Department = department;
department.Staff.Add(employee);

var options = new JsonSerializerOptions
{
    ReferenceHandler = ReferenceHandler.Preserve
};

var jsonString = JsonSerializer.Serialize(department, options);

Here, we set the ReferenceHandler property to ReferenceHandler.Preserve. With this, we instruct the serializer to preserve the object graph structure by including metadata in the serialized objects, and resolve reverence loops using pointers based on generated unique object identifiers:

"$id": "1",
"Name": "Human Resources",
"Staff": {
"$id": "2",
"$values": [
"$id": "3",
"FirstName": "John",
"LastName": "Smith",
"Department": {
"$ref": "1"
{
  "$id": "1",
  "Name": "Human Resources",
  "Staff": {
    "$id": "2",
    "$values": [
      {
        "$id": "3",
        "FirstName": "John",
        "LastName": "Smith",
        "Department": {
          "$ref": "1"
        }
      }
    ]
  }
}

Alternatively, we can use the ReferenceHandler.IgnoreCycles value to tell the serializer to simply ignore circular references:

"Name": "Human Resources",
"Staff": [
"FirstName": "John",
"LastName": "Smith",
"Department": null
{
  "Name": "Human Resources",
  "Staff": [
    {
      "FirstName": "John",
      "LastName": "Smith",
      "Department": null
    }
  ]
}

On the other hand, with Newtonsoft our only option is to ignore the loop references using the JsonSerializerSettings.ReferenceLoopHandling property:

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

Conclusion

In this article, we have learned how to turn a C# object into a JSON string. For that, we learned how to use System.Text.Json and Newtonsoft Json.NET as well.

We’ve learned how to customize various aspects of the serialization process like indentation, property capitalization, how to ignore specific properties, or how to change the date and time format. We also learned what reference loops are and how to deal with them.

Finally, remember that we can find many other examples of how to work with System.Text.Json on this website.

Code Maze Book Collection

Want to build great APIs? Or become even better at it? Check our Ultimate ASP.NET Core Web API program and learn how to create a full production-ready ASP.NET Core API using only the latest .NET technologies. Bonus materials (Security book, Docker book, and other bonus files) are included in the Premium package!

Share:

Subscribe
guest
Label
0 Comments
booklet-200px-width-min.png

--- FREE eBook ---
Top 16 BEST PRACTICES
to improve API effectiveness 10x.
Find out how!

Leave this field empty if you're human:

© Copyright code-maze.com 2016 - 2022

wpDiscuz


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK