How do I get formatted JSON in .NET using C#? - c#

I am using .NET JSON parser and would like to serialize my config file so it is readable. So instead of:
{"blah":"v", "blah2":"v2"}
I would like something nicer like:
{
"blah":"v",
"blah2":"v2"
}
My code is something like this:
using System.Web.Script.Serialization;
var ser = new JavaScriptSerializer();
configSz = ser.Serialize(config);
using (var f = (TextWriter)File.CreateText(configFn))
{
f.WriteLine(configSz);
f.Close();
}

You are going to have a hard time accomplishing this with JavaScriptSerializer.
Try JSON.Net.
With minor modifications from JSON.Net example
using System;
using Newtonsoft.Json;
namespace JsonPrettyPrint
{
internal class Program
{
private static void Main(string[] args)
{
Product product = new Product
{
Name = "Apple",
Expiry = new DateTime(2008, 12, 28),
Price = 3.99M,
Sizes = new[] { "Small", "Medium", "Large" }
};
string json = JsonConvert.SerializeObject(product, Formatting.Indented);
Console.WriteLine(json);
Product deserializedProduct = JsonConvert.DeserializeObject<Product>(json);
}
}
internal class Product
{
public String[] Sizes { get; set; }
public decimal Price { get; set; }
public DateTime Expiry { get; set; }
public string Name { get; set; }
}
}
Results
{
"Sizes": [
"Small",
"Medium",
"Large"
],
"Price": 3.99,
"Expiry": "\/Date(1230447600000-0700)\/",
"Name": "Apple"
}
Documentation: Serialize an Object

A shorter sample code for Json.Net library
private static string FormatJson(string json)
{
dynamic parsedJson = JsonConvert.DeserializeObject(json);
return JsonConvert.SerializeObject(parsedJson, Formatting.Indented);
}

If you have a JSON string and want to "prettify" it, but don't want to serialise it to and from a known C# type then the following does the trick (using JSON.NET):
using System;
using System.IO;
using Newtonsoft.Json;
class JsonUtil
{
public static string JsonPrettify(string json)
{
using (var stringReader = new StringReader(json))
using (var stringWriter = new StringWriter())
{
var jsonReader = new JsonTextReader(stringReader);
var jsonWriter = new JsonTextWriter(stringWriter) { Formatting = Formatting.Indented };
jsonWriter.WriteToken(jsonReader);
return stringWriter.ToString();
}
}
}

Shortest version to prettify existing JSON: (edit: using JSON.net)
JToken.Parse("mystring").ToString()
Input:
{"menu": { "id": "file", "value": "File", "popup": { "menuitem": [ {"value": "New", "onclick": "CreateNewDoc()"}, {"value": "Open", "onclick": "OpenDoc()"}, {"value": "Close", "onclick": "CloseDoc()"} ] } }}
Output:
{
"menu": {
"id": "file",
"value": "File",
"popup": {
"menuitem": [
{
"value": "New",
"onclick": "CreateNewDoc()"
},
{
"value": "Open",
"onclick": "OpenDoc()"
},
{
"value": "Close",
"onclick": "CloseDoc()"
}
]
}
}
}
To pretty-print an object:
JToken.FromObject(myObject).ToString()

Oneliner using Newtonsoft.Json.Linq:
string prettyJson = JToken.Parse(uglyJsonString).ToString(Formatting.Indented);

Net Core App
var js = JsonSerializer.Serialize(obj, new JsonSerializerOptions {
WriteIndented = true
});

All this can be done in one simple line:
string jsonString = JsonConvert.SerializeObject(yourObject, Formatting.Indented);

Here is a solution using Microsoft's System.Text.Json library:
static string FormatJsonText(string jsonString)
{
using var doc = JsonDocument.Parse(
jsonString,
new JsonDocumentOptions
{
AllowTrailingCommas = true
}
);
MemoryStream memoryStream = new MemoryStream();
using (
var utf8JsonWriter = new Utf8JsonWriter(
memoryStream,
new JsonWriterOptions
{
Indented = true
}
)
)
{
doc.WriteTo(utf8JsonWriter);
}
return new System.Text.UTF8Encoding()
.GetString(memoryStream.ToArray());
}

You may use following standard method for getting formatted Json
JsonReaderWriterFactory.CreateJsonWriter(Stream stream, Encoding encoding, bool ownsStream, bool indent, string indentChars)
Only set "indent==true"
Try something like this
public readonly DataContractJsonSerializerSettings Settings =
new DataContractJsonSerializerSettings
{ UseSimpleDictionaryFormat = true };
public void Keep<TValue>(TValue item, string path)
{
try
{
using (var stream = File.Open(path, FileMode.Create))
{
//var currentCulture = Thread.CurrentThread.CurrentCulture;
//Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
try
{
using (var writer = JsonReaderWriterFactory.CreateJsonWriter(
stream, Encoding.UTF8, true, true, " "))
{
var serializer = new DataContractJsonSerializer(type, Settings);
serializer.WriteObject(writer, item);
writer.Flush();
}
}
catch (Exception exception)
{
Debug.WriteLine(exception.ToString());
}
finally
{
//Thread.CurrentThread.CurrentCulture = currentCulture;
}
}
}
catch (Exception exception)
{
Debug.WriteLine(exception.ToString());
}
}
Pay your attention to lines
var currentCulture = Thread.CurrentThread.CurrentCulture;
Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
....
Thread.CurrentThread.CurrentCulture = currentCulture;
For some kinds of xml-serializers you should use InvariantCulture to avoid exception during deserialization on the computers with different Regional settings. For example, invalid format of double or DateTime sometimes cause them.
For deserializing
public TValue Revive<TValue>(string path, params object[] constructorArgs)
{
try
{
using (var stream = File.OpenRead(path))
{
//var currentCulture = Thread.CurrentThread.CurrentCulture;
//Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
try
{
var serializer = new DataContractJsonSerializer(type, Settings);
var item = (TValue) serializer.ReadObject(stream);
if (Equals(item, null)) throw new Exception();
return item;
}
catch (Exception exception)
{
Debug.WriteLine(exception.ToString());
return (TValue) Activator.CreateInstance(type, constructorArgs);
}
finally
{
//Thread.CurrentThread.CurrentCulture = currentCulture;
}
}
}
catch
{
return (TValue) Activator.CreateInstance(typeof (TValue), constructorArgs);
}
}
Thanks!

Using System.Text.Json set JsonSerializerOptions.WriteIndented = true:
JsonSerializerOptions options = new JsonSerializerOptions { WriteIndented = true };
string json = JsonSerializer.Serialize<Type>(object, options);

2023 Update
For those who ask how I get formatted JSON in .NET using C# and want to see how to use it right away and one-line lovers. Here are the indented JSON string one-line codes:
There are 2 well-known JSON formatter or parsers to serialize:
Newtonsoft Json.Net version:
using Newtonsoft.Json;
var jsonString = JsonConvert.SerializeObject(yourObj, Formatting.Indented);
.Net 7 version:
using System.Text.Json;
var jsonString = JsonSerializer.Serialize(yourObj, new JsonSerializerOptions { WriteIndented = true });

using System.Text.Json;
...
var parsedJson = JsonSerializer.Deserialize<ExpandoObject>(json);
var options = new JsonSerializerOptions() { WriteIndented = true };
return JsonSerializer.Serialize(parsedJson, options);

First I wanted to add comment under Duncan Smart post, but unfortunately I have not got enough reputation yet to leave comments. So I will try it here.
I just want to warn about side effects.
JsonTextReader internally parses json into typed JTokens and then serialises them back.
For example if your original JSON was
{ "double":0.00002, "date":"\/Date(1198908717056)\/"}
After prettify you get
{
"double":2E-05,
"date": "2007-12-29T06:11:57.056Z"
}
Of course both json string are equivalent and will deserialize to structurally equal objects, but if you need to preserve original string values, you need to take this into concideration

I have something very simple for this. You can put as input really any object to be converted into json with a format:
private static string GetJson<T> (T json)
{
return JsonConvert.SerializeObject(json, Formatting.Indented);
}

This worked for me. In case someone is looking for a VB.NET version.
#imports System
#imports System.IO
#imports Newtonsoft.Json
Public Shared Function JsonPrettify(ByVal json As String) As String
Using stringReader = New StringReader(json)
Using stringWriter = New StringWriter()
Dim jsonReader = New JsonTextReader(stringReader)
Dim jsonWriter = New JsonTextWriter(stringWriter) With {
.Formatting = Formatting.Indented
}
jsonWriter.WriteToken(jsonReader)
Return stringWriter.ToString()
End Using
End Using
End Function

.NET 5 has built in classes for handling JSON parsing, serialization, deserialization under System.Text.Json namespace. Below is an example of a serializer which converts a .NET object to a JSON string,
using System.Text.Json;
using System.Text.Json.Serialization;
private string ConvertJsonString(object obj)
{
JsonSerializerOptions options = new JsonSerializerOptions();
options.WriteIndented = true; //Pretty print using indent, white space, new line, etc.
options.NumberHandling = JsonNumberHandling.AllowNamedFloatingPointLiterals; //Allow NANs
string jsonString = JsonSerializer.Serialize(obj, options);
return jsonString;
}

Below code works for me:
JsonConvert.SerializeObject(JToken.Parse(yourobj.ToString()))

For UTF8 encoded JSON file using .NET Core 3.1, I was finally able to use JsonDocument based upon this information from Microsoft: https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-how-to#utf8jsonreader-utf8jsonwriter-and-jsondocument
string allLinesAsOneString = string.Empty;
string [] lines = File.ReadAllLines(filename, Encoding.UTF8);
foreach(var line in lines)
allLinesAsOneString += line;
JsonDocument jd = JsonDocument.Parse(Encoding.UTF8.GetBytes(allLinesAsOneString));
var writer = new Utf8JsonWriter(Console.OpenStandardOutput(), new JsonWriterOptions
{
Indented = true
});
JsonElement root = jd.RootElement;
if( root.ValueKind == JsonValueKind.Object )
{
writer.WriteStartObject();
}
foreach (var jp in root.EnumerateObject())
jp.WriteTo(writer);
writer.WriteEndObject();
writer.Flush();

Related

How to create JSON object in C#

I need to create JSON like this:
{
"files": [
{
"file_path": "example.txt",
"content" : "source code \n with multiple lines\n"
}
]
}
But my code (I serialized it to JSON later) doesn't correspond to this example above
var requestBody = new
{
files = new string[] { snippet.FileName, snippet.Content }
};
Can someone help me :)?
EDIT:
my serialization method:
protected string serializeToJson( object obj )
{
return JsonConvert.SerializeObject( obj, new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() } );
}
Try That:
using System.Text.Json;
var obj = new
{
files = new[]
{
new
{
file_path = "example.txt",
content ="source code \n with multiple lines\n"
}
}
};
var json = JsonSerializer.Serialize(obj);
Console.WriteLine(json);
Result:
We can make use of the serializeobject to convert into json
string jsonStr = JsonConvert.SerializeObject(obj);
This method will be available in the newtonsoft package

c# Json get value from list sourced from usgs url

I need help extracting and returning values from json as either doubles or string, either should be fine.
The URL being used it: <https://earthquake.usgs.gov/ws/designmaps/asce7-16.json?latitude=34&longitude=-118&riskCategory=III&siteClass=C&title=Example>
here is the json
{
"request": {
"date": "2021-01-30T19:07:52.176Z",
"referenceDocument": "ASCE7-16",
"status": "success",
"url": "https://earthquake.usgs.gov/ws/designmaps/asce7-16.json?latitude=34&longitude=-118&riskCategory=III&siteClass=C&title=Example",
"parameters": {
"latitude": 34,
"longitude": -118,
"riskCategory": "III",
"siteClass": "C",
"title": "Example"
}
},
"response": {
"data": {
"pgauh": 0.819,
"pgad": 1.021,
"pga": 0.819,
"fpga": 1.2,
"pgam": 0.983,
"ssrt": 1.888,
"crs": 0.896,
"ssuh": 2.106,
"ssd": 2.432,
"ss": 1.888,
"fa": 1.2,
"sms": 2.265,
"sds": 1.51,
"sdcs": "D",
"s1rt": 0.669,
"cr1": 0.9,
"s1uh": 0.743,
"s1d": 0.963,
"s1": 0.669,
"fv": 1.4,
"sm1": 0.936,
"sd1": 0.624,
"sdc1": "D",
"sdc": "D",
"tl": 8,
"t-sub-l": 8,
"cv": 1.278,
...
url is defined as an input and Ss and S1 are defined as outputs per VisualStudio 2019 grasshopper developer C# template.
right now Ss and S1 return null values, they should return 1.888 and 0.669, respectively.
using Grasshopper.Kernel;
using System;
using System.Net;
using Newtonsoft.Json.Linq;
protected override void SolveInstance(IGH_DataAccess DA)
{
string url = "";
DA.GetData(0, ref url);
using (WebClient wc = new WebClient())
{
var json = wc.DownloadString(url);
JObject jObj = JObject.Parse(json); // Parse the object graph
string Ss = (string)jObj["ss"];
string S1 = (string)jObj["s1"];
//Functions I also tried
//var data = jObj["data"];
//foreach (var d in data) ;
//var Ss = d["ss"];
//double Ss = jObj.GetValue("ss").ToObject<double>();
//string Ss = jObj.GetValue("ss").Value<string>();
//string Ss = jObj.GetValue("ss").ToString();
//string Ss = jObj["ss"].ToString();
DA.SetData(0, Ss);
DA.SetData(1, S1);
}
}
The information you are looking for is nested in two levels, you have to access the response object then the data object, this should work:
var json = wc.DownloadString(url);
JObject jObj = JObject.Parse(json); // Parse the object graph
var data = jObj["response"]["data"];
var ss = data["ss"].ToObject<double>(); // or .ToString() if you want the string value
var s1 = data["s1"].ToObject<double>(); // or .ToString() if you want the string value
DA.SetData(0, ss);
DA.SetData(1, s1);
note: this code lacks null checks and error handling (try-catch block) for the sake of simplicity. But you need to add that in your code.
your data is null, is because your need Deserilize Json
using httpclientFactory
var httpclient = _httpClientFactory.CreateClient();
var responseDatas = await httpclient.GetAsync("https://earthquake.usgs.gov/ws/designmaps/asce7-16.json?latitude=34&longitude=-118&riskCategory=III&siteClass=C&title=Example");
if (responseDatas.IsSuccessStatusCode)
{
var responseDatasJson = await responseDatas .Content.ReadAsStringAsync();
var options = new JsonSerializerOptions() { PropertyNameCaseInsensitive = true };
var resultDataJson = JsonSerializer.Deserialize<Root>(responseDatasJson, options);
return (resultDataJson);
}
for convert json to c# class use this site Json to c# class
or use visual studio options
Edit-->Paste Special-->Paste Json As Classes
public class Data {
public double ss{ get; set; }
public double s1{ get; set; }
....your properties
}
public class Response {
public Data data { get; set; }
}
public class Root {
public Response response { get; set; }
}

How to output JSON array as a single field in CSV using ChoETL

I'm using ChoETL to convert JSON to CSV. Currently, if a property in the JSON object is an array it is output into separate fields in JSON.
Example:
{
"id", 1234,
"states": [
"PA",
"VA"
]
},
{
"id", 1235,
"states": [
"CA",
"DE",
"MD"
]
},
This results in CSV like this (using pipe as a delimeter)
"id"|"states_0"|"states_1"|"states_2"
"1234"|"PA"|"VA"
"1235"|"CA"|"DE"|"MD"
What I would like is for the array to be displayed in a single states field as a comma separated string
"id"|"states"
"1234"|"PA,VA"
"1235"|"CA,DE,MD"
Here is the code I have in place to perform the parsing and transformation.
public static class JsonCsvConverter
{
public static string ConvertJsonToCsv(string json)
{
var csvData = new StringBuilder();
using (var jsonReader = ChoJSONReader.LoadText(json))
{
using (var csvWriter = new ChoCSVWriter(csvData).WithFirstLineHeader())
{
csvWriter.WithMaxScanRows(1000);
csvWriter.Configuration.Delimiter = "|";
csvWriter.Configuration.QuoteAllFields = true;
csvWriter.Write(jsonReader);
}
}
return csvData.ToString();
}
}
Edited: Removed test code that wasn't useful
This is how you can produce the expected output using the code below
var csvData = new StringBuilder();
using (var jsonReader = ChoJSONReader.LoadText(json))
{
using (var csvWriter = new ChoCSVWriter(csvData)
.WithFirstLineHeader()
.WithDelimiter("|")
.QuoteAllFields()
.Configure(c => c.UseNestedKeyFormat = false)
.WithField("id")
.WithField("states", m => m.ValueConverter(o => String.Join(",", ((Array)o).OfType<string>())))
)
{
csvWriter.Write(jsonReader);
}
}
Console.WriteLine(csvData.ToString());
Output:
id|states
"1234"|"PA,VA"
"1235"|"CA,DE,MD"
PS: on the next release, this issue will be handled automatically without using valueconverters

howto Serialize data consist an array using JsonWriter in C#

I'm looking for something that can be Serialize data that consist an Array using JsonWriter in C#?
This is an error that im getting:
ExceptionMessage: "Unsupported type: Module.Model.Acl_Entries[]. Use the JsonSerializer class to get the object's JSON representation. Path 'acl_entries'."
ExceptionType: "Newtonsoft.Json.JsonWriterException"
This is my Data:
"author": {
"stakeholder_id": "stkh-a23ee7909d024a21a54fb60d60089c97",
"username": "alex",
"acl_entries": [{
"stakeholder_id": "stkh-f8e80f32aad44df6a7a96b20d4fee340",
"stakeholder_name": "james",
"stakeholder_type_id": "5"
}]
}
}
This is my Controller:
public class AuthorRequest
{
public Stakeholder author { get; set; }
}
[HttpPut]
[ActionName("PutUpdateStakeholder")]
public string PutUpdateStakeholder(AuthorRequest request)
{
var author = request.author;
List <Stakeholder> list = _repos.PutUpdateStakeholder(author);
//Utils.Log("stakeBasic" + author );
return JsonConvert.SerializeObject(list);
}
This is my JsonWriter:
public List<Stakeholder> PutUpdateStakeholder(Stakeholder author)
{
Utils.Log("Update>>>" + author);
string sMsg = "";
StringWriter sw = new StringWriter();
using (JsonWriter writer = new JsonTextWriter(sw))
{
writer.Formatting = Formatting.None;
writer.WriteStartObject();
object obj = null;
object fal = false;
object tr = true;
object val = 0;
writer.WritePropertyName("stakeholder_id");
writer.WriteValue(author.stakeholder_id);
writer.WritePropertyName("username");
writer.WriteValue(author.username);
writer.WritePropertyName("acl_entries"); //array
writer.WriteStartArray();
//writer.WriteStartObject();
writer.WriteValue(author.acl_entries);
//writer.WriteEndObject();
writer.WriteEnd();
writer.WriteEndObject();
}
string sParam = "param=" + sw.ToString();
string sResp = "";
Utils.Log("BASIC" + sParam);
List<Stakeholder> list = new List<Stakeholder>();
if (Utils.GenerateRequest("Stakeholder", sParam, "PUT", ref sResp))
{
Utils.deserializeStakeholderResp(sResp, ref list, ref sMsg);
//Utils.Log("BASIC" + sParam);
}
else
{
sMsg += sResp;
}
return list;
}
So my question is, how can i Serialize Data that consist an Array using JsonWriter in C# or maybe someone could give me a hint on this.
What the JsonWriter require for a writer.WriteStartArray() is a simple object like [1,2,3,4,5] or ['a','b','c] i.e. is an array of type integer or string.
But what you are feeding in it is an object-array:
"acl_entries": [{
"stakeholder_id": "stkh-f8e80f32aad44df6a7a96b20d4fee340",
"stakeholder_name": "james",
"stakeholder_type_id": "5"
}]
Which the JsonWriter is not able to get the type of. So, you have two options:
Convert the array object into a json string and put it in the object acl_entries (i.e.that is serialize it) as:
JavaScriptSerializer serializera = new JavaScriptSerializer();
string res = serializera.Serialize(author.acl_entries);
jsonWriter.WriteValue(res);
Note: you can also use Newtonsoft.json for it.
Or as it is explained in the How to serialize nested collection using JsonWriter by OP is:
start an array object - > loop through all the entries to create an object of each entry and then end the array-object.
you can change your code to something like this:
writer.WritePropertyName("acl_entries");
jsonWriter.WriteStartArray();
for (int row = 0; row <= author.acl_entries.Count; row++)
{
jsonWriter.WriteStartObject();
jsonWriter.WritePropertyName("stakeholder_id");
jsonWriter.WriteValue(author.acl_entries[row].stakeholder_id);
jsonWriter.WritePropertyName("stakeholder_name");
jsonWriter.WriteValue(author.acl_entries[row].stakeholder_name);
jsonWriter.WritePropertyName("stakeholder_type_id");
jsonWriter.WriteValue(author.acl_entries[row].stakeholder_type_id);
jsonWriter.WriteEndObject();
}
jsonWriter.WriteEndArray();
Note: You can modify the above logic to have a dynamic implementation where you don't have to hardcode the fields and their value getters.

Json.net deserialize DateTime from HTTPClient result

I am using HTTPCLient to call RestFul service. My problem when parsing DateTime.
Because in my class I have DateTime Property. Which in Json it is type long. Json key is: exp
{
"resultCodes": "OK",
"description": "OK",
"pans": {
"maskedPan": [
{
"id": "4b533683-bla-bla-3517",
"pan": "67*********98",
"exp": 1446321600000,
"isDefault": true
},
{
"id": "a3093f00-zurna-01e18a8d4d72",
"pan": "57*********96",
"exp": 1554058800000,
"isDefault": false
}
]
}
}
In documentation i read that
To minimize memory usage and the number of objects allocated Json.NET supports serializing and deserializing directly to a stream.
So =>
WAY 1 (Reading via GetStringAsync). In documentation has written that use StreamReader instead.
return Task.Factory.StartNew(() =>
{
var client = new HttpClient(_handler);
var url = String.Format(_baseUrl + #"list/{0}", sessionId);
BillsList result;
var rrrrr = client.GetStringAsync(url).Result;
result = JsonConvert.DeserializeObject<BillsList>(rrrrr,
new MyDateTimeConverter());
return result;
}, cancellationToken);
WAY 2(Good way. I read via StreamReader. Bu in line var rTS = sr.ReadToEnd(); it creates new string. It is not good. Because i have used GetStreamAsync to avoid of creating string variable.)
return Task.Factory.StartNew(() =>
{
var client = new HttpClient(_handler);
var url = String.Format(_baseUrl + #"list/{0}", sessionId);
BillsList result;
using (var s = client.GetStreamAsync(url).Result)
using (var sr = new StreamReader(s))
using (JsonReader reader = new JsonTextReader(sr))
{
var rTS = sr.ReadToEnd();
result = JsonConvert.DeserializeObject<BillsList>(rTS,
new MyDateTimeConverter());
}
return result;
}, cancellationToken);
WAY 3(The best. But it gives exception if property is DateTime in my class. )
return Task.Factory.StartNew(() =>
{
var client = new HttpClient(_handler);
var url = String.Format(_baseUrl + #"list/{0}", sessionId);
BillsList result;
using (var s = client.GetStreamAsync(url).Result)
using (var sr = new StreamReader(s))
using (JsonReader reader = new JsonTextReader(sr))
{
var serializer = new JsonSerializer();
result = serializer.Deserialize<BillsList>(reader);
}
return result;
}, cancellationToken);
So my question. I want to continue with 3-rd way. But have there any way to set some handler as MyDateTimeConverter for JsonSerializer to convert it automatically?
You can set up default JsonSerializerSettings when your app is initialized:
// This needs to be done only once, so put it in an appropriate static initializer.
JsonConvert.DefaultSettings = () => new JsonSerializerSettings
{
Converters = new List<JsonConverter> { new MyDateTimeConverter() }
};
Then later you can use JsonSerializer.CreateDefault
JsonSerializer serializer = JsonSerializer.CreateDefault();
result = serializer.Deserialize<BillsList>(reader);
You can add your MyDateTimeConverter to the Converters collection on the JsonSerializer; that should allow you to use your third approach without getting errors.
var serializer = new JsonSerializer();
serializer.Converters.Add(new MyDateTimeConverter());
result = serializer.Deserialize<BillsList>(reader);

Categories