JSON, XML and HTML values
editJSON, XML or HTML embedded in a value is hard to read and compare on one line. Formatters rewrite it: they apply to JsonNode, JsonDocument and JsonElement values, to XmlNode and XElement values, and to the content of HTTP messages, according to its media type.
JSON and XML
var options = new HumanReadableSerializerOptions()
.AddJsonFormatter(new JsonFormatterOptions { OrderProperties = true })
.AddXmlFormatter(new XmlFormatterOptions { OrderAttributes = true });
var value = new
{
Json = JsonNode.Parse("""{"name":"Ada","id":42}"""),
Xml = XElement.Parse("""<user name="Ada" id="42"><role>admin</role></user>"""),
};
Assert.Equal("""
Json:
{
"id": 42,
"name": "Ada"
}
Xml:
<user id="42" name="Ada">
<role>admin</role>
</user>
""", HumanReadableSerializer.Serialize(value, options));| Method | Media types | Options |
|---|---|---|
AddJsonFormatter(JsonFormatterOptions?) | application/json, text/json, *+json | WriteIndented (default true), OrderProperties (default false), FormatAsStandardObject (default false) |
AddXmlFormatter(XmlFormatterOptions?) | application/xml, text/xml, *+xml | WriteIndented (default true), OrderAttributes (default false) |
AddUrlEncodedFormFormatter(UrlEncodedFormFormatterOptions?) | application/x-www-form-urlencoded | OrderProperties, UnescapeValues and PrettyFormat (default true) |
Without a formatter, the value is written as it is. A value that cannot be parsed, such as invalid JSON, is written as it is too.
FormatAsStandardObject writes the JSON as the serializer writes objects, without braces and quotes:
var options = new HumanReadableSerializerOptions()
.AddJsonFormatter(new JsonFormatterOptions { FormatAsStandardObject = true });
var value = new { Json = JsonNode.Parse("""{"name":"Ada","roles":["admin","dev"]}""") };
Assert.Equal("""
Json:
name: Ada
roles:
- admin
- dev
""", HumanReadableSerializer.Serialize(value, options));HTML
The Meziantou.Framework.HumanReadableSerializer.Html package adds a formatter for text/html values:
dotnet package add Meziantou.Framework.HumanReadableSerializer.Htmlusing var content = new StringContent(
"""<p id='greeting' class=intro nonce=r4nd0m>Hello<br/>world & all</p>""",
encoding: null,
"text/html");
var options = new HumanReadableSerializerOptions()
.AddHtmlFormatter(new HtmlFormatterOptions
{
OrderAttributes = true,
RedactContentSecurityPolicyNonce = true,
});
Assert.Equal("""
Headers:
Content-Type: text/html; charset=utf-8
Value: <p class="intro" id="greeting" nonce="[redacted]">Hello<br>world & all</p>
""", HumanReadableSerializer.Serialize(content, options));The value is parsed by the HTML parser of Meziantou.Framework.WebPlatform, which follows the HTML specification, and serialized back, so the output is normalized: attribute values are quoted, character references are decoded and escaped again, and <br/> becomes <br>. Two HTML values that differ only by these details give the same text.
| Option | Description |
|---|---|
| OrderAttributes | Sorts the attributes of each element by namespace and name |
| AttributeQuote | HtmlAttributeQuote.DoubleQuote (the default) or HtmlAttributeQuote.SimpleQuote |
| RedactContentSecurityPolicyNonce | Replaces the value of the nonce attributes with [redacted], as a nonce changes on every response |
A value that contains a doctype or an html, head or body tag is parsed as a document, and keeps these elements:
using var content = new StringContent("""<!DOCTYPE html><html lang=en><body><a href="/docs">Docs</a></body></html>""", encoding: null, "text/html");
var options = new HumanReadableSerializerOptions()
.AddHtmlFormatter(new HtmlFormatterOptions { AttributeQuote = HtmlAttributeQuote.SimpleQuote });
// A document keeps its doctype, html, head and body elements
Assert.Equal("""
Headers:
Content-Type: text/html; charset=utf-8
Value: <!DOCTYPE html><html lang='en'><head></head><body><a href='/docs'>Docs</a></body></html>
""", HumanReadableSerializer.Serialize(content, options));Any other value is parsed as the content of a body element, and written without the elements the parser adds around it. A value that cannot be formatted is written as it is.
Other media types
AddFormatter(mediaType, formatter) registers a ValueFormatter for any media type. A formatter overrides Format(writer, value, options) and writes the value with the HumanReadableTextWriter. The ValueFormatter constants name the media types the serializer recognizes: JsonMediaTypeName, XmlMediaTypeName, HtmlMediaTypeName, WwwFormUrlEncodedMediaTypeName, CssMediaTypeName and JavascriptMediaTypeName.