Working with JSON in .NET: A Comprehensive Guide
Every developer must have used JSON in their life. Json.NET was the library that Microsoft used in their every framework from Mobile to Web. Now Microsoft has released their own library for JSON that is written from scratch and is highly performant. In this article, we will explore the new JSON API provided by Microsoft.
Table of Contents
- Serialize POCO to JSON
- Customize property names
- How to Deserialize JSON to POCO
- How to print Indented JSON
- Camel case for all JSON property names
- Use a custom JSON property naming policy
- Convert Enum to String
- Ignore Property
- Ignore Read-Only Properties
- Convert Property Value while Serializing
Serialize POCO to JSON
Let’s start with a basic example. Consider the following code snippet where we are serializing a POCO (Plain Old CLR Object) class to JSON:
void Main()
{
var response = new ResponseJson
{
Status = true,
Message = "my message",
LogId = "my log id",
LogStatus = "my log status"
};
var json = JsonSerializer.Serialize(response);
Console.WriteLine("Serialized {0}", response);
Console.WriteLine(json);
}
public class ResponseJson
{
public bool Status { get; set; }
public string Message { get; set; }
public string LogId { get; set; }
public string LogStatus { get; set; }
}
Serialized ResponseJson
{"Status":true,"Message":"my message","LogId":"my log id","LogStatus":"my log status"}
Customize property names
By default, the JSON property name is the same as the C# property name. If you want to control the name of the JSON property, you can use the JsonPropertyName
attribute as shown below:
public class ResponseJson
{
[JsonPropertyName("status")]
public bool Status { get; set; }
[JsonPropertyName("message")]
public string Message { get; set; }
[JsonPropertyName("Log_id")]
public string LogId { get; set; }
[JsonPropertyName("Log_status")]
public string LogStatus { get; set; }
}
output
Serialized ResponseJson
{"status":true,"message":"my message","Log_id":"my log id","Log_status":"my log status"}
How to Deserialize JSON to POCO
To deserialize JSON into a POCO class, you can use the JsonSerializer.Deserialize
method. Here’s an example:
{
"status":true,
"message":"my message",
"Log_id":"my log id",
"Log_status":"my log status"
}
void Main()
{
var jsonResponse="{\"Status\":true,\"Message\":\"my message\",\"LogId\":\"my log id\",\"LogStatus\":\"my log status\"}";
var json = JsonSerializer.Deserialize<ResponseJson>(jsonResponse);
Console.WriteLine("Serialized {0}", json);
Console.WriteLine(json);
}
How to print Indented JSON
If you want to print indented JSON output, then you can pass JsonSerializerOptions
and set the property WriteIndented=true
void Main()
{
var response = new ResponseJson
{
Status = true,
Message = "my message",
LogId = "my log id",
LogStatus = "my log status",
FailureReason = "my failure reason"
};
var options = new JsonSerializerOptions
{
WriteIndented = true,
};
var json = JsonSerializer.Serialize(response, options);
Console.WriteLine("Serialized {0}", response);
Console.WriteLine(json);
}
{
"Status": true,
"Message": "my message",
"LogId": "my log id",
"LogStatus": "my log status",
"FailureReason": "my failure reason"
}
Camel case for all JSON property names
By default, the JSON property names match the C# property names. If you want to convert them to camel case, you can use the JsonNamingPolicy.CamelCase
option as shown below:
void Main()
{
var response = new ResponseJson
{
Status = true,
Message = "my message",
LogId = "my log id",
LogStatus = "my log status"
};
var serializeOptions = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
WriteIndented = true
};
var json = JsonSerializer.Serialize(response, serializeOptions);
Console.WriteLine("Serialized {0}", response);
Console.WriteLine(json);
}
Serialized ResponseJson
{
"status": true,
"message": "my message",
"logId": "my log id",
"logStatus": "my log status"
}
Use a custom JSON property naming policy
Assume you want to change the JSON property name before sending it to the server. You can easily do it using the Microsoft JSON library
Step 1: Create a custom class and implement the JsonNamingPolicy
abstract class
public class SnakeNamePolicy : JsonNamingPolicy
{
public override string ConvertName(string name)
{
return ToUnderscoreCase(name);
}
private string ToUnderscoreCase(string str)
=> string.Concat((str ?? string.Empty).Select((x, i) => i > 0 && char.IsUpper(x) && !char.IsUpper(str[i - 1]) ? $"_{x}" : x.ToString())).ToLower();
}
In the ConvertName
method, write the transformation logic. In this example, I’m converting the name to snake case.
Step 2: Pass the newly created policy to JsonSerializerOptions
and use it in the Serialize
method
void Main()
{
var response = new ResponseJson
{
Status = true,
Message = "my message",
LogId = "my log id",
LogStatus = "my log status"
};
var serializeOptions = new JsonSerializerOptions
{
PropertyNamingPolicy = new SnakeNamePolicy(),
WriteIndented = true
};
var json = JsonSerializer.Serialize(response, serializeOptions);
Console.WriteLine("Serialized {0}", response);
Console.WriteLine(json);
}
By passing the SnakeNamePolicy
instance to PropertyNamingPolicy
in the JsonSerializerOptions
, the property names will be transformed to snake case during serialization.
ouput
Serialized ResponseJson
{
"status": true,
"message": "my message",
"log_id": "my log id",
"log_status": "my log status"
}
Convert Enum to String
By default, enums are serialized as their underlying integer values. If you want to serialize enums as strings, you can use the JsonStringEnumConverter
attribute. Here’s an example:
var serializeOptions = new JsonSerializerOptions
{
Converters =
{
new JsonStringEnumConverter(JsonNamingPolicy.CamelCase)
}
};
public class ResponseJson
{
public bool Status { get; set; }
public string Message { get; set; }
public string LogId { get; set; }
public string LogStatus { get; set; }
public Severity Severity { get; set; }
}
public enum Severity
{
Low,
High,
Critical
}
void Main()
{
var response = new ResponseJson
{
Status = true,
Message = "my message",
LogId = "my log id",
LogStatus = "my log status",
Severity = Severity.Critical
};
var serializeOptions = new JsonSerializerOptions
{
Converters =
{
new JsonStringEnumConverter(JsonNamingPolicy.CamelCase)
}
};
var json = JsonSerializer.Serialize(response, serializeOptions);
Console.WriteLine("Serialized {0}", response);
Console.WriteLine(json);
}
Output
Serialized ResponseJson
{"Status":true,"Message":"my message","LogId":"my log id","LogStatus":"my log status","Severity":"critical"}
Ignore Property
If you want to exclude a property from serialization and deserialization, you can use the JsonIgnore
attribute. Here’s an example:
public class ResponseJson
{
[JsonIgnore]
public bool Status { get; set; }
// ...
}
Ignore Read-Only Properties
By default, read-only properties are not serialized. If you want to include them in the serialization, you can use the IgnoreReadOnlyProperties
attribute. Here’s an example:
var options = new JsonSerializerOptions
{
IgnoreReadOnlyProperties = true,
WriteIndented = true
};
jsonString = JsonSerializer.Serialize(weatherForecast, options);
Convert Property Value while Serializing
This is a compelling feature of the Microsoft Serializer library. Let’s suppose you want to serialize a property, but you want to do some preprocessing before that. In this example, I am converting the string to Base64.
void Main()
{
var response = new ResponseJson
{
Status = true,
Message = "my message",
LogId = "my log id",
LogStatus = "my log status",
Severity = Severity.Critical
};
var json = JsonSerializer.Serialize(response);
Console.WriteLine("Serialized {0}", response);
Console.WriteLine(json);
}
public class StringToBase64JsonConvertor : JsonConverter<string>
{
public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return reader.GetString().ToLower();
}
public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options)
{
writer.WriteBase64StringValue(Encoding.UTF8.GetBytes(value));
}
}
public class ResponseJson
{
public bool Status { get; set; }
public string Message { get; set; }
public string LogId { get; set; }
[JsonConverter(typeof(StringToBase64JsonConvertor))]
public string LogStatus { get; set; }
public Severity Severity { get; set; }
}
public enum Severity
{
Low,
High,
Critical
}
Output
Serialized ResponseJson
{"Status":true,"Message":"my message","LogId":"my log id","LogStatus":"bXkgbG9nIHN0YXR1cw==","Severity":2}
Conclusion
Serialization
and deserialization of JSON data in .NET provide a powerful and flexible way to work with JSON. You can control various aspects of the process, such as property naming, enum serialization, property exclusion, and custom conversion. These features allow you to fine-tune how your C# objects are represented in JSON, making it easier to work with JSON-based APIs and data interchange.
In this blog post, we explored some of the key concepts and techniques related to JSON serialization and deserialization in .NET. I hope this information helps you in your JSON handling tasks. Happy coding!