TL;DR: Is there a built-in way in ServiceStack.Text to produce pretty-printed JSON?
I am using ServiceStack.Text for doing JSON serialization. It works really good so far, but the created JSON (using .ToJSON()
) is not formated with whitespaces or newlines (most likely to save space when sending over the network). However, in some circumstances it would be nice to have the JSON formatted for easier human-readability.
The .Dump ()
method does some sort of formatting, however does not produce valid JSON (i.e. the surrounding doublequotes are missing).
The T.Dump()
and T.PrintDump()
extension methods in ServiceStack.Text are just a pretty formatted version of the JSV Format that's created with the TypeSerializer class or T.ToJsv()
Extension method. It is only to provide a human friendly dump of data, it's not parseable.
The new string.IndentJson()
extension method available from v4.5.5 will let you pretty-print JSON otherwise you can install a Pretty JSONView extension for Chrome or Firefox to see pretty JSON or you can paste the JSON in jsonprettyprint.com
Having a pretty json format would be good from the servicestack text. As a workaround because I created a a plugin to format the json when I needed it. Hopefully a future release of service stack I can get rid of this code.
Download the dll from the link below, (it gives you an extension method to format the json)
http://www.markdavidrogers.com/json-pretty-printerbeautifier-library-for-net/
I used this in stead of something like json.net as I wanted to make sure I did not change the servicestack serialization of the json.
Then I created the following pluging
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using JsonPrettyPrinterPlus;
using ServiceStack.Common.Web;
using ServiceStack.ServiceClient.Web;
using ServiceStack.ServiceHost;
using ServiceStack.ServiceModel.Serialization;
using ServiceStack.ServiceModel.Support;
using ServiceStack.WebHost.Endpoints;
namespace Bm.Services.Plugins
{
public class PrettyJsonFormatPlugin : IPlugin
{
public const string JsonPrettyText = "application/prettyjson";
public void Register(IAppHost appHost)
{
appHost.ContentTypeFilters.Register(JsonPrettyText,
Serialize,
Deserialize);
}
public static void Serialize(IRequestContext requestContext, object dto, Stream outputStream)
{
var json = HttpResponseFilter.Instance.Serialize(ContentType.Json, dto);
json = json.PrettyPrintJson();
byte[] bytes = Encoding.UTF8.GetBytes(json);
outputStream.Write(bytes, 0, bytes.Length);
}
public static object Deserialize(Type type, Stream fromStream)
{
var obj = JsonDataContractDeserializer.Instance.DeserializeFromStream(type, fromStream);
return obj;
}
}
public class PrettyJsonServiceClient : JsonServiceClient
{
public PrettyJsonServiceClient() : base()
{
}
public PrettyJsonServiceClient(string baseUri) : base(baseUri)
{
}
public PrettyJsonServiceClient(string syncReplyBaseUri, string asyncOneWayBaseUri) : base(syncReplyBaseUri, asyncOneWayBaseUri)
{
}
public override string Format
{
get
{
return "prettyjson";
}
}
}
}
In you startup code register the new plugin
EndpointHost.AddPlugin(new PrettyJsonFormatPlugin());
To call an example service from c#
var prettyJsonClient = new PrettyJsonServiceClient(HOST_URL);
var ret = prettyJsonClient.Get<string>(@"/system/ping/test");
Here is an equivilent xml one
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Bm.Core;
using JsonPrettyPrinterPlus;
using ServiceStack.Common.Web;
using ServiceStack.ServiceClient.Web;
using ServiceStack.ServiceHost;
using ServiceStack.ServiceModel.Serialization;
using ServiceStack.ServiceModel.Support;
using ServiceStack.WebHost.Endpoints;
namespace Bm.Services.Plugins
{
public class PrettyXmlFormatPlugin : IPlugin
{
public const string XmlPrettyText = "application/prettyxml";
public void Register(IAppHost appHost)
{
appHost.ContentTypeFilters.Register(XmlPrettyText,
Serialize,
Deserialize);
}
public static void Serialize(IRequestContext requestContext, object dto, Stream outputStream)
{
var xml = HttpResponseFilter.Instance.Serialize(ContentType.Xml, dto);
xml = Common.PrettyXml(xml);
byte[] bytes = Encoding.UTF8.GetBytes(xml);
outputStream.Write(bytes, 0, bytes.Length);
}
public static object Deserialize(Type type, Stream fromStream)
{
var obj = JsonDataContractDeserializer.Instance.DeserializeFromStream(type, fromStream);
return obj;
}
}
public class PrettyXmlServiceClient : XmlServiceClient
{
public PrettyXmlServiceClient()
: base()
{
}
public PrettyXmlServiceClient(string baseUri)
: base(baseUri)
{
}
public PrettyXmlServiceClient(string syncReplyBaseUri, string asyncOneWayBaseUri)
: base(syncReplyBaseUri, asyncOneWayBaseUri)
{
}
public override string Format
{
get
{
return "prettyxml";
}
}
}
}
To get pretty JSON:
var formattedJson = JsvFormatter.Format(JsonSerializer.SerializeToString(dto));
The resulting json string can be parsed back:
var dto = JsonSerializer.DeserializeFromString<MyDto>(formattedJson);