Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pretty-print (format) System.Text.JsonElement to a string

Where is the API to format an existing JsonElement to a formatted JSON string. The ToString() API does not provide any formatting options.

Falling back to using Newtonsoft is pretty annoying

Newtonsoft.Json.Linq.JValue
  .Parse(myJsonElement.GetRawText())
  .ToString(Newtonsoft.Json.Formatting.Indented)
like image 776
Aaron Hudon Avatar asked May 04 '20 18:05

Aaron Hudon


2 Answers

You can re-serialize your JsonElement with JsonSerializer and set JsonSerializerOptions.WriteIndented = true, e.g. in an extension method:

public static partial class JsonExtensions
{
    public static string ToString(this JsonElement element, bool indent)
        => element.ValueKind == JsonValueKind.Undefined ? "" : JsonSerializer.Serialize(element, new JsonSerializerOptions { WriteIndented = indent } );
}

And then do:

var indentedJson = myJsonElement.ToString(true)

Notes:

  • The check for JsonValueKind.Undefined is to avoid an exception with a default (uninitialized) JsonElement struct; JsonElement.ToString() does not throw for a default JsonElement so neither should the formatted version.

  • Writing using a Utf8JsonWriter while setting JsonWriterOptions.Indented as shown in the other answers will also work.

Demo fiddle here.

like image 162
dbc Avatar answered Sep 28 '22 08:09

dbc


You should be able to use an extension class like this if you don't want to use json.net:

public static class JsonElementExtension
{
    private static readonly JsonWriterOptions s_indentedOptions = new JsonWriterOptions()
    {
        Indented = true
    };

    public static string ToStringIndented(this JsonElement value)
    {
        using MemoryStream stream = new MemoryStream();
        using Utf8JsonWriter writer = new Utf8JsonWriter(stream, s_indentedOptions);
        value.WriteTo(writer);
        writer.Flush();
        string indented = Encoding.UTF8.GetString(stream.GetBuffer(), 0, (int)stream.Length);

        return indented;
    }
}

Seems to work fine and it should be pretty efficient too :)

Benchmark

I couldn't help myself

|                 Method |           TestObj |          Mean |         Error |        StdDev |        Median |      Gen 0 |     Gen 1 |   Gen 2 |   Allocated |
|----------------------- |------------------ |--------------:|--------------:|--------------:|--------------:|-----------:|----------:|--------:|------------:|
|              IndentDbc | L | Length: 12728 |     64.677 us |     1.2955 us |     2.7327 us |     63.557 us |     9.1553 |    2.3193 |       - |    37.87 KB |
|          IndentJoelius | L | Length: 12728 |     57.765 us |     0.4019 us |     0.3563 us |     57.876 us |    23.8037 |         - |       - |    97.59 KB |
|     IndentDbcTimes1000 | L | Length: 12728 | 62,935.262 us |   580.6653 us |   543.1547 us | 63,025.312 us |  9250.0000 | 2250.0000 |       - | 37874.29 KB |
| IndentJoeliusTimes1000 | L | Length: 12728 | 58,882.179 us | 1,171.0801 us | 1,891.0761 us | 58,067.511 us | 23777.7778 |         - |       - | 97585.94 KB |
|              IndentDbc |  M | Length: 4282 |     28.480 us |     0.0503 us |     0.0393 us |     28.474 us |     4.4556 |    1.5259 |       - |    18.38 KB |
|          IndentJoelius |  M | Length: 4282 |     22.645 us |     0.1426 us |     0.1334 us |     22.678 us |     9.3384 |    0.0305 |       - |     38.3 KB |
|     IndentDbcTimes1000 |  M | Length: 4282 | 28,966.720 us |   563.5127 us |   752.2733 us | 28,607.184 us |  4468.7500 | 1468.7500 |       - |    18382 KB |
| IndentJoeliusTimes1000 |  M | Length: 4282 | 22,310.261 us |   131.5337 us |   123.0367 us | 22,322.828 us |  9343.7500 |   31.2500 |       - | 38304.69 KB |
|              IndentDbc |   S | Length: 360 |      9.929 us |     0.2096 us |     0.4468 us |      9.699 us |     1.4648 |    0.7324 |  0.0305 |     6.02 KB |
|          IndentJoelius |   S | Length: 360 |      2.375 us |     0.0138 us |     0.0129 us |      2.380 us |     1.6747 |         - |       - |     6.84 KB |
|     IndentDbcTimes1000 |   S | Length: 360 |  9,700.109 us |   190.5759 us |   187.1710 us |  9,701.489 us |  1468.7500 |  734.3750 | 31.2500 |  6017.83 KB |
| IndentJoeliusTimes1000 |   S | Length: 360 |  2,471.567 us |    48.7855 us |    74.5006 us |  2,432.958 us |  1671.8750 |         - |       - |  6843.75 KB |
Code
[MemoryDiagnoser]
public class PrettyPrintJson
{
    private const string SmallJsonString = "{\"glossary\":{\"title\":\"example glossary\",\"GlossDiv\":{\"title\":\"S\",\"GlossList\":{\"GlossEntry\":{\"ID\":\"SGML\",\"SortAs\":\"SGML\",\"GlossTerm\":\"Standard Generalized Markup Language\",\"Acronym\":\"SGML\",\"Abbrev\":\"ISO 8879:1986\",\"GlossDef\":{\"para\":\"A meta-markup language, used to create markup languages such as DocBook.\",\"GlossSeeAlso\":[\"GML\",\"XML\"]},\"GlossSee\":\"markup\"}}}}}";
    private const string MediumJsonString = "{\"web-app\":{\"servlet\":[{\"servlet-name\":\"cofaxCDS\",\"servlet-class\":\"org.cofax.cds.CDSServlet\",\"init-param\":{\"configGlossary:installationAt\":\"Philadelphia, PA\",\"configGlossary:adminEmail\":\"[email protected]\",\"configGlossary:poweredBy\":\"Cofax\",\"configGlossary:poweredByIcon\":\"/images/cofax.gif\",\"configGlossary:staticPath\":\"/content/static\",\"templateProcessorClass\":\"org.cofax.WysiwygTemplate\",\"templateLoaderClass\":\"org.cofax.FilesTemplateLoader\",\"templatePath\":\"templates\",\"templateOverridePath\":\"\",\"defaultListTemplate\":\"listTemplate.htm\",\"defaultFileTemplate\":\"articleTemplate.htm\",\"useJSP\":false,\"jspListTemplate\":\"listTemplate.jsp\",\"jspFileTemplate\":\"articleTemplate.jsp\",\"cachePackageTagsTrack\":200,\"cachePackageTagsStore\":200,\"cachePackageTagsRefresh\":60,\"cacheTemplatesTrack\":100,\"cacheTemplatesStore\":50,\"cacheTemplatesRefresh\":15,\"cachePagesTrack\":200,\"cachePagesStore\":100,\"cachePagesRefresh\":10,\"cachePagesDirtyRead\":10,\"searchEngineListTemplate\":\"forSearchEnginesList.htm\",\"searchEngineFileTemplate\":\"forSearchEngines.htm\",\"searchEngineRobotsDb\":\"WEB-INF/robots.db\",\"useDataStore\":true,\"dataStoreClass\":\"org.cofax.SqlDataStore\",\"redirectionClass\":\"org.cofax.SqlRedirection\",\"dataStoreName\":\"cofax\",\"dataStoreDriver\":\"com.microsoft.jdbc.sqlserver.SQLServerDriver\",\"dataStoreUrl\":\"jdbc:microsoft:sqlserver://LOCALHOST:1433;DatabaseName=goon\",\"dataStoreUser\":\"sa\",\"dataStorePassword\":\"dataStoreTestQuery\",\"dataStoreTestQuery\":\"SET NOCOUNT ON;select test='test';\",\"dataStoreLogFile\":\"/usr/local/tomcat/logs/datastore.log\",\"dataStoreInitConns\":10,\"dataStoreMaxConns\":100,\"dataStoreConnUsageLimit\":100,\"dataStoreLogLevel\":\"debug\",\"maxUrlLength\":500}},{\"servlet-name\":\"cofaxEmail\",\"servlet-class\":\"org.cofax.cds.EmailServlet\",\"init-param\":{\"mailHost\":\"mail1\",\"mailHostOverride\":\"mail2\"}},{\"servlet-name\":\"cofaxAdmin\",\"servlet-class\":\"org.cofax.cds.AdminServlet\"},{\"servlet-name\":\"fileServlet\",\"servlet-class\":\"org.cofax.cds.FileServlet\"},{\"servlet-name\":\"cofaxTools\",\"servlet-class\":\"org.cofax.cms.CofaxToolsServlet\",\"init-param\":{\"templatePath\":\"toolstemplates/\",\"log\":1,\"logLocation\":\"/usr/local/tomcat/logs/CofaxTools.log\",\"logMaxSize\":\"\",\"dataLog\":1,\"dataLogLocation\":\"/usr/local/tomcat/logs/dataLog.log\",\"dataLogMaxSize\":\"\",\"removePageCache\":\"/content/admin/remove?cache=pages&id=\",\"removeTemplateCache\":\"/content/admin/remove?cache=templates&id=\",\"fileTransferFolder\":\"/usr/local/tomcat/webapps/content/fileTransferFolder\",\"lookInContext\":1,\"adminGroupID\":4,\"betaServer\":true}}],\"servlet-mapping\":{\"cofaxCDS\":\"/\",\"cofaxEmail\":\"/cofaxutil/aemail/*\",\"cofaxAdmin\":\"/admin/*\",\"fileServlet\":\"/static/*\",\"cofaxTools\":\"/tools/*\"},\"taglib\":{\"taglib-uri\":\"cofax.tld\",\"taglib-location\":\"/WEB-INF/tlds/cofax.tld\"},\"widgets\":[{\"widget\":{\"debug\":\"on\",\"window\":{\"title\":\"Sample Konfabulator Widget\",\"name\":\"main_window\",\"width\":500,\"height\":500},\"image\":{\"src\":\"Images/Sun.png\",\"name\":\"sun1\",\"hOffset\":250,\"vOffset\":250,\"alignment\":\"center\"},\"text\":{\"data\":\"Click Here\",\"size\":36,\"style\":\"bold\",\"name\":\"text1\",\"hOffset\":250,\"vOffset\":100,\"alignment\":\"center\",\"onMouseUp\":\"sun1.opacity = (sun1.opacity / 100) * 90;\"}}},{\"widget\":{\"debug\":\"on\",\"window\":{\"title\":\"Sample Konfabulator Widget\",\"name\":\"main_window\",\"width\":500,\"height\":500},\"image\":{\"src\":\"Images/Sun.png\",\"name\":\"sun1\",\"hOffset\":250,\"vOffset\":250,\"alignment\":\"center\"},\"text\":{\"data\":\"Click Here\",\"size\":36,\"style\":\"bold\",\"name\":\"text1\",\"hOffset\":250,\"vOffset\":100,\"alignment\":\"center\",\"onMouseUp\":\"sun1.opacity = (sun1.opacity / 100) * 90;\"}}},{\"widget\":{\"debug\":\"on\",\"window\":{\"title\":\"Sample Konfabulator Widget\",\"name\":\"main_window\",\"width\":500,\"height\":500},\"image\":{\"src\":\"Images/Sun.png\",\"name\":\"sun1\",\"hOffset\":250,\"vOffset\":250,\"alignment\":\"center\"},\"text\":{\"data\":\"Click Here\",\"size\":36,\"style\":\"bold\",\"name\":\"text1\",\"hOffset\":250,\"vOffset\":100,\"alignment\":\"center\",\"onMouseUp\":\"sun1.opacity = (sun1.opacity / 100) * 90;\"}}},{\"widget\":{\"debug\":\"on\",\"window\":{\"title\":\"Sample Konfabulator Widget\",\"name\":\"main_window\",\"width\":500,\"height\":500},\"image\":{\"src\":\"Images/Sun.png\",\"name\":\"sun1\",\"hOffset\":250,\"vOffset\":250,\"alignment\":\"center\"},\"text\":{\"data\":\"Click Here\",\"size\":36,\"style\":\"bold\",\"name\":\"text1\",\"hOffset\":250,\"vOffset\":100,\"alignment\":\"center\",\"onMouseUp\":\"sun1.opacity = (sun1.opacity / 100) * 90;\"}}}]}}";
    private const string LargeJsonString = "[{\"_id\":\"5eb269d7e263a650fa521fce\",\"index\":0,\"guid\":\"7bd247fd-1cca-4bca-a11e-f08fefb2fd88\",\"isActive\":true,\"balance\":\"$1,661.65\",\"picture\":\"http://placehold.it/32x32\",\"age\":38,\"eyeColor\":\"brown\",\"name\":\"Vang Pruitt\",\"gender\":\"male\",\"company\":\"MEMORA\",\"email\":\"[email protected]\",\"phone\":\"+1 (941) 540-3024\",\"address\":\"981 Woodpoint Road, Lumberton, Georgia, 436\",\"about\":\"Adipisicing quis quis esse cillum do aliqua cupidatat. Veniam quis sint veniam consequat incididunt nostrud irure consectetur fugiat Lorem consectetur culpa. Eu nisi voluptate reprehenderit excepteur officia irure. Commodo et pariatur minim sit sunt voluptate in in consectetur.\\r\\n\",\"registered\":\"2019-05-26T06:33:18 -02:00\",\"latitude\":2.802999,\"longitude\":87.398184,\"tags\":[\"exercitation\",\"in\",\"minim\",\"ut\",\"ad\",\"amet\",\"ex\"],\"friends\":[{\"id\":0,\"name\":\"Fulton Booth\"},{\"id\":1,\"name\":\"Janice Raymond\"},{\"id\":2,\"name\":\"Leonard Guerra\"}],\"greeting\":\"Hello, Vang Pruitt! You have 9 unread messages.\",\"favoriteFruit\":\"strawberry\"},{\"_id\":\"5eb269d71d47d0aa8caf8e5d\",\"index\":1,\"guid\":\"6e25dc1e-b01d-462b-9bd3-f762601a70b5\",\"isActive\":true,\"balance\":\"$3,073.30\",\"picture\":\"http://placehold.it/32x32\",\"age\":24,\"eyeColor\":\"brown\",\"name\":\"Fuentes Wilkins\",\"gender\":\"male\",\"company\":\"QUONK\",\"email\":\"[email protected]\",\"phone\":\"+1 (912) 409-3864\",\"address\":\"925 Seagate Avenue, Juntura, Tennessee, 7256\",\"about\":\"Laborum aute voluptate id aute ipsum. Aliqua proident cillum sit anim pariatur tempor sit non anim et. Anim adipisicing exercitation exercitation ad aliquip commodo.\\r\\n\",\"registered\":\"2019-10-12T01:23:03 -02:00\",\"latitude\":11.285935,\"longitude\":168.307644,\"tags\":[\"amet\",\"veniam\",\"eiusmod\",\"anim\",\"elit\",\"sit\",\"aliquip\"],\"friends\":[{\"id\":0,\"name\":\"Rebekah Hooper\"},{\"id\":1,\"name\":\"Luz Clay\"},{\"id\":2,\"name\":\"Briana Navarro\"}],\"greeting\":\"Hello, Fuentes Wilkins! You have 7 unread messages.\",\"favoriteFruit\":\"banana\"},{\"_id\":\"5eb269d7baa30b3c10c95ed1\",\"index\":2,\"guid\":\"fbdfd5e2-4be7-44aa-82e0-a8d629f2814e\",\"isActive\":true,\"balance\":\"$1,140.06\",\"picture\":\"http://placehold.it/32x32\",\"age\":20,\"eyeColor\":\"brown\",\"name\":\"Maryellen Barrera\",\"gender\":\"female\",\"company\":\"PRINTSPAN\",\"email\":\"[email protected]\",\"phone\":\"+1 (972) 598-3416\",\"address\":\"254 Doughty Street, Loyalhanna, Oregon, 6496\",\"about\":\"Anim sunt pariatur amet adipisicing Lorem sint eu. Qui incididunt deserunt eu irure quis ea ipsum sit Lorem anim velit. Excepteur ex ex cillum dolor duis sunt est ad cupidatat nisi minim elit consectetur. Ullamco consequat velit magna minim.\\r\\n\",\"registered\":\"2019-12-01T11:32:41 -01:00\",\"latitude\":-82.018912,\"longitude\":58.634407,\"tags\":[\"enim\",\"tempor\",\"culpa\",\"magna\",\"qui\",\"minim\",\"aliquip\"],\"friends\":[{\"id\":0,\"name\":\"Molly Wilder\"},{\"id\":1,\"name\":\"Marci Owen\"},{\"id\":2,\"name\":\"Brooke Walsh\"}],\"greeting\":\"Hello, Maryellen Barrera! You have 7 unread messages.\",\"favoriteFruit\":\"apple\"},{\"_id\":\"5eb269d7d540e816e540b786\",\"index\":3,\"guid\":\"fc338dab-0efa-4042-b606-15ec5bd90b3a\",\"isActive\":true,\"balance\":\"$3,485.52\",\"picture\":\"http://placehold.it/32x32\",\"age\":25,\"eyeColor\":\"blue\",\"name\":\"Hattie Roman\",\"gender\":\"female\",\"company\":\"REVERSUS\",\"email\":\"[email protected]\",\"phone\":\"+1 (920) 519-2691\",\"address\":\"875 Story Court, Veguita, Maine, 3325\",\"about\":\"Non excepteur Lorem ex veniam. Cillum eu laboris proident tempor dolore quis pariatur in culpa excepteur elit id duis. Tempor tempor laborum nisi aliquip.\\r\\n\",\"registered\":\"2015-03-27T09:41:39 -01:00\",\"latitude\":-77.496931,\"longitude\":-1.023251,\"tags\":[\"cillum\",\"aliqua\",\"cillum\",\"occaecat\",\"amet\",\"fugiat\",\"dolor\"],\"friends\":[{\"id\":0,\"name\":\"Dale Weiss\"},{\"id\":1,\"name\":\"Prince Tran\"},{\"id\":2,\"name\":\"Pamela Wise\"}],\"greeting\":\"Hello, Hattie Roman! You have 3 unread messages.\",\"favoriteFruit\":\"banana\"},{\"_id\":\"5eb269d766574e33d43c73d7\",\"index\":4,\"guid\":\"2a7c5444-3c37-4ca2-b528-1df3cb0efab5\",\"isActive\":true,\"balance\":\"$2,654.88\",\"picture\":\"http://placehold.it/32x32\",\"age\":33,\"eyeColor\":\"green\",\"name\":\"Yvette Mooney\",\"gender\":\"female\",\"company\":\"CANDECOR\",\"email\":\"[email protected]\",\"phone\":\"+1 (923) 589-2519\",\"address\":\"881 Kay Court, Dowling, Palau, 1405\",\"about\":\"Elit eu voluptate veniam laborum ea proident occaecat nulla Lorem ex sint ex. Labore id fugiat dolor ut anim tempor occaecat. Ad aute esse Lorem reprehenderit qui id sunt exercitation laborum.\\r\\n\",\"registered\":\"2015-12-13T06:40:16 -01:00\",\"latitude\":44.69473,\"longitude\":-109.342104,\"tags\":[\"amet\",\"cupidatat\",\"minim\",\"veniam\",\"deserunt\",\"anim\",\"sit\"],\"friends\":[{\"id\":0,\"name\":\"Claudine Love\"},{\"id\":1,\"name\":\"Sharlene Lang\"},{\"id\":2,\"name\":\"Webb Fletcher\"}],\"greeting\":\"Hello, Yvette Mooney! You have 9 unread messages.\",\"favoriteFruit\":\"strawberry\"},{\"_id\":\"5eb269d71a1100165255375d\",\"index\":5,\"guid\":\"755d3011-34da-4774-aaff-0d7615d0e4fe\",\"isActive\":false,\"balance\":\"$3,882.18\",\"picture\":\"http://placehold.it/32x32\",\"age\":30,\"eyeColor\":\"green\",\"name\":\"Head Montgomery\",\"gender\":\"male\",\"company\":\"BULLJUICE\",\"email\":\"[email protected]\",\"phone\":\"+1 (978) 584-3910\",\"address\":\"664 George Street, Motley, Illinois, 8776\",\"about\":\"Sunt minim non eiusmod reprehenderit nulla veniam officia nulla sunt ullamco cillum Lorem et. Reprehenderit eu duis fugiat sunt tempor aliquip commodo nostrud. In deserunt et exercitation tempor exercitation sint elit aliquip tempor est consectetur. Duis sunt eu laboris nostrud aliqua mollit magna. Nostrud anim labore cupidatat consectetur eu sint reprehenderit cillum voluptate id consectetur pariatur consequat minim.\\r\\n\",\"registered\":\"2016-12-02T07:39:43 -01:00\",\"latitude\":35.628237,\"longitude\":97.750618,\"tags\":[\"ex\",\"consectetur\",\"id\",\"officia\",\"cillum\",\"labore\",\"occaecat\"],\"friends\":[{\"id\":0,\"name\":\"Potter Cook\"},{\"id\":1,\"name\":\"Church Watts\"},{\"id\":2,\"name\":\"Kathy Olson\"}],\"greeting\":\"Hello, Head Montgomery! You have 5 unread messages.\",\"favoriteFruit\":\"strawberry\"},{\"_id\":\"5eb269d7147f54bbfd73a920\",\"index\":6,\"guid\":\"f757168b-660a-41ff-a410-2d7d4031f0ff\",\"isActive\":false,\"balance\":\"$2,641.71\",\"picture\":\"http://placehold.it/32x32\",\"age\":30,\"eyeColor\":\"blue\",\"name\":\"Carla Ware\",\"gender\":\"female\",\"company\":\"MEDCOM\",\"email\":\"[email protected]\",\"phone\":\"+1 (914) 409-2524\",\"address\":\"482 Burnett Street, Courtland, Federated States Of Micronesia, 6331\",\"about\":\"Cillum ea enim nulla et voluptate in. Laborum voluptate sit ut cupidatat irure culpa in deserunt. Enim sit laborum sunt ex eu exercitation aliqua voluptate.\\r\\n\",\"registered\":\"2019-02-02T12:33:07 -01:00\",\"latitude\":61.206412,\"longitude\":-99.105565,\"tags\":[\"enim\",\"consectetur\",\"esse\",\"aliquip\",\"elit\",\"adipisicing\",\"anim\"],\"friends\":[{\"id\":0,\"name\":\"Wagner Collins\"},{\"id\":1,\"name\":\"Stephanie Terry\"},{\"id\":2,\"name\":\"Wilkerson Maddox\"}],\"greeting\":\"Hello, Carla Ware! You have 5 unread messages.\",\"favoriteFruit\":\"apple\"},{\"_id\":\"5eb269d72e5476f4153fb7f9\",\"index\":7,\"guid\":\"7fd3213c-65e3-4d30-859d-c666c6eb2231\",\"isActive\":false,\"balance\":\"$3,748.30\",\"picture\":\"http://placehold.it/32x32\",\"age\":25,\"eyeColor\":\"blue\",\"name\":\"Rebecca Sheppard\",\"gender\":\"female\",\"company\":\"EXPOSA\",\"email\":\"[email protected]\",\"phone\":\"+1 (918) 449-3202\",\"address\":\"225 Vandervoort Place, Condon, North Dakota, 4941\",\"about\":\"Est magna consectetur ex elit esse. Deserunt consequat sint anim adipisicing eu labore ex ut amet. Eu velit duis sunt ipsum. Elit cupidatat et eu qui aliquip deserunt incididunt ex mollit consectetur ipsum. Esse non anim dolore minim magna amet velit exercitation velit.\\r\\n\",\"registered\":\"2017-05-31T08:20:38 -02:00\",\"latitude\":-64.19375,\"longitude\":-65.280295,\"tags\":[\"minim\",\"culpa\",\"commodo\",\"mollit\",\"dolore\",\"culpa\",\"velit\"],\"friends\":[{\"id\":0,\"name\":\"Dawson Gates\"},{\"id\":1,\"name\":\"Frost Jensen\"},{\"id\":2,\"name\":\"Weaver Burks\"}],\"greeting\":\"Hello, Rebecca Sheppard! You have 9 unread messages.\",\"favoriteFruit\":\"strawberry\"},{\"_id\":\"5eb269d7b6f75e7ab91f6133\",\"index\":8,\"guid\":\"9a867aa7-168b-4848-a8b6-2aedb0de6d83\",\"isActive\":false,\"balance\":\"$3,026.27\",\"picture\":\"http://placehold.it/32x32\",\"age\":31,\"eyeColor\":\"green\",\"name\":\"Jordan Franklin\",\"gender\":\"female\",\"company\":\"COMFIRM\",\"email\":\"[email protected]\",\"phone\":\"+1 (852) 593-2144\",\"address\":\"270 Crawford Avenue, Wilmington, Arizona, 6180\",\"about\":\"Occaecat ut non anim consectetur excepteur exercitation do excepteur do quis eiusmod. Est minim sunt consequat exercitation minim cupidatat ea et. Ea ex excepteur eu tempor adipisicing Lorem duis. Culpa dolore ut sit ut consectetur pariatur dolore incididunt aliqua anim incididunt. Qui et proident commodo sit dolor veniam dolore culpa dolor nisi deserunt reprehenderit labore excepteur. Anim ad commodo aliquip laboris deserunt. Fugiat ea duis eiusmod in officia occaecat irure et.\\r\\n\",\"registered\":\"2019-01-17T09:53:56 -01:00\",\"latitude\":18.477444,\"longitude\":-26.502142,\"tags\":[\"cupidatat\",\"magna\",\"exercitation\",\"eu\",\"consequat\",\"aliquip\",\"adipisicing\"],\"friends\":[{\"id\":0,\"name\":\"Elsie Morrow\"},{\"id\":1,\"name\":\"Carmen Dennis\"},{\"id\":2,\"name\":\"Yang Frye\"}],\"greeting\":\"Hello, Jordan Franklin! You have 3 unread messages.\",\"favoriteFruit\":\"apple\"},{\"_id\":\"5eb269d7c37d3ea8eac1d92f\",\"index\":9,\"guid\":\"7820c5e9-9c39-4793-9384-b00f4d3fc9c6\",\"isActive\":false,\"balance\":\"$3,519.28\",\"picture\":\"http://placehold.it/32x32\",\"age\":36,\"eyeColor\":\"brown\",\"name\":\"Harmon Richardson\",\"gender\":\"male\",\"company\":\"BRAINCLIP\",\"email\":\"[email protected]\",\"phone\":\"+1 (967) 408-3810\",\"address\":\"416 Wyona Street, Urbana, Oklahoma, 5317\",\"about\":\"Reprehenderit officia ex officia proident ipsum occaecat sit incididunt magna non exercitation quis. Et cupidatat minim sit irure nostrud ea esse. Enim aliqua occaecat exercitation cupidatat dolore qui excepteur fugiat nostrud do id ad. Irure amet dolor elit quis excepteur consectetur laborum aliqua esse ad laboris aliqua laboris elit. Esse dolor et incididunt reprehenderit sit ex anim minim commodo ex duis anim excepteur fugiat.\\r\\n\",\"registered\":\"2014-01-09T06:14:50 -01:00\",\"latitude\":-11.892063,\"longitude\":171.301135,\"tags\":[\"deserunt\",\"in\",\"mollit\",\"commodo\",\"fugiat\",\"in\",\"officia\"],\"friends\":[{\"id\":0,\"name\":\"Deloris Simmons\"},{\"id\":1,\"name\":\"Helena Decker\"},{\"id\":2,\"name\":\"Rodriquez Lowe\"}],\"greeting\":\"Hello, Harmon Richardson! You have 10 unread messages.\",\"favoriteFruit\":\"banana\"},{\"_id\":\"5eb269d7abe2360eb55c9238\",\"index\":10,\"guid\":\"bb224e15-c05e-42fc-aa4b-eb877b9caf83\",\"isActive\":false,\"balance\":\"$2,046.03\",\"picture\":\"http://placehold.it/32x32\",\"age\":31,\"eyeColor\":\"brown\",\"name\":\"Rutledge Holloway\",\"gender\":\"male\",\"company\":\"QUINTITY\",\"email\":\"[email protected]\",\"phone\":\"+1 (812) 523-3577\",\"address\":\"924 Wakeman Place, Caroline, Florida, 448\",\"about\":\"Voluptate nostrud incididunt cupidatat occaecat nisi amet consectetur tempor commodo pariatur aute tempor eiusmod voluptate. Sint cillum labore ullamco consequat elit labore. In et ipsum officia exercitation sint exercitation minim laboris nisi Lorem ad. Exercitation duis magna exercitation ex aliquip elit sint amet fugiat tempor fugiat. Minim deserunt incididunt cupidatat occaecat ipsum ipsum dolore incididunt laboris. Aute cupidatat fugiat dolor est non. Consequat velit fugiat irure officia cillum mollit ad cillum aliqua in labore occaecat dolore.\\r\\n\",\"registered\":\"2019-04-11T03:15:57 -02:00\",\"latitude\":63.608152,\"longitude\":29.757405,\"tags\":[\"elit\",\"irure\",\"dolore\",\"labore\",\"ut\",\"dolor\",\"veniam\"],\"friends\":[{\"id\":0,\"name\":\"Darcy Wolf\"},{\"id\":1,\"name\":\"Bridget Rocha\"},{\"id\":2,\"name\":\"Garrison Ford\"}],\"greeting\":\"Hello, Rutledge Holloway! You have 6 unread messages.\",\"favoriteFruit\":\"apple\"},{\"_id\":\"5eb269d77706c5051bab9e2c\",\"index\":11,\"guid\":\"f814c8da-7104-4e30-b9bf-4e8ae02cd93f\",\"isActive\":false,\"balance\":\"$1,159.77\",\"picture\":\"http://placehold.it/32x32\",\"age\":25,\"eyeColor\":\"brown\",\"name\":\"Teri Farrell\",\"gender\":\"female\",\"company\":\"EVEREST\",\"email\":\"[email protected]\",\"phone\":\"+1 (881) 437-3416\",\"address\":\"168 Ashford Street, Basye, Arkansas, 1990\",\"about\":\"Anim ut commodo elit eu. Esse eu sunt aute pariatur sunt in. Ea adipisicing ullamco sunt labore officia dolore aute incididunt. Ut id irure occaecat laborum cupidatat ut occaecat. Reprehenderit tempor consequat ullamco mollit nisi anim laboris culpa irure. Laboris cillum ut reprehenderit deserunt incididunt velit id dolor magna consectetur. Non voluptate irure deserunt aliqua officia cillum cillum excepteur nisi dolor excepteur sint esse.\\r\\n\",\"registered\":\"2017-12-09T07:59:34 -01:00\",\"latitude\":-58.989994,\"longitude\":155.72163,\"tags\":[\"nulla\",\"aliqua\",\"sunt\",\"est\",\"do\",\"aute\",\"quis\"],\"friends\":[{\"id\":0,\"name\":\"Kristin Goodman\"},{\"id\":1,\"name\":\"Mamie Short\"},{\"id\":2,\"name\":\"Cynthia Goodwin\"}],\"greeting\":\"Hello, Teri Farrell! You have 1 unread messages.\",\"favoriteFruit\":\"strawberry\"}]";

    private const int N = 1000;

    [ParamsSource(nameof(ValuesForTestObj))]
    public JsonTestObject TestObj { get; set; }

    public static IEnumerable<JsonTestObject> ValuesForTestObj() => new[]
    {
        new JsonTestObject(SmallJsonString, "S"),
        new JsonTestObject(MediumJsonString, "M"),
        new JsonTestObject(LargeJsonString, "L")
    };

    [Benchmark]
    public void IndentDbc()
    {
        JsonExtensions.ToString(TestObj.Element, true);
    }

    [Benchmark]
    public void IndentJoelius()
    {
        JsonElementExtension.ToStringIndented(TestObj.Element);
    }

    [Benchmark]
    public void IndentDbcTimes1000()
    {
        for (int i = 0; i < N; i++)
        {
            JsonExtensions.ToString(TestObj.Element, true);
        }
    }

    [Benchmark]
    public void IndentJoeliusTimes1000()
    {
        for (int i = 0; i < N; i++)
        {
            JsonElementExtension.ToStringIndented(TestObj.Element);
        }
    }

    public class JsonTestObject
    {
        private readonly string _jsonString;
        private readonly string _display;
        public JsonElement Element { get; }

        public JsonTestObject(string json, string display)
        {
            _jsonString = json;
            _display = display;
            Element = JsonSerializer.Deserialize<JsonElement>(_jsonString);
        }

        public override string ToString() =>
            $"{_display} | Length: {_jsonString.Length}";
    }
}

internal static class JsonElementExtension
{
    private static readonly JsonWriterOptions s_indentedOptions = new JsonWriterOptions()
    {
        Indented = true
    };

    public static string ToStringIndented(this JsonElement value)
    {
        using MemoryStream stream = new MemoryStream();
        using Utf8JsonWriter writer = new Utf8JsonWriter(stream, s_indentedOptions);
        value.WriteTo(writer);
        writer.Flush();
        string indented = Encoding.UTF8.GetString(stream.GetBuffer(), 0, (int)stream.Length);

        return indented;
    }
}

internal static class JsonExtensions
{
    public static string ToString(this JsonElement element, bool indent)
        => element.ValueKind == JsonValueKind.Undefined ? "" : JsonSerializer.Serialize(element, new JsonSerializerOptions { WriteIndented = indent });
}

public class Program
{
    public static void Main(string[] args)
    {
        var summary = BenchmarkRunner.Run<PrettyPrintJson>();
        Console.WriteLine(summary);
    }
}
like image 22
Joelius Avatar answered Sep 28 '22 10:09

Joelius