Reputation: 29785
I need to read a JSON configuration file, modify a value and then save the modified JSON back to the file again. The JSON is as simple as it gets:
{
"test": "init",
"revision": 0
}
To load the data and modify the value I do this:
var config = JObject.Parse(File.ReadAllText("config.json"));
config["revision"] = 1;
So far so good; now, to write the JSON back to the file. First I tried this:
File.WriteAllText("config.json", config.ToString(Formatting.Indented));
Which writes the file correctly, but the indentation is only two spaces.
{
"test": "init",
"revision": 1
}
From the documentation, it looks like there's no way to pass any other options in using this method, so I tried modifying this example which would allow me to directly set the Indentation
and IndentChar
properties of the JsonTextWriter
to specify the amount of indentation:
using (FileStream fs = File.Open("config.json", FileMode.OpenOrCreate))
{
using (StreamWriter sw = new StreamWriter(fs))
{
using (JsonTextWriter jw = new JsonTextWriter(sw))
{
jw.Formatting = Formatting.Indented;
jw.IndentChar = ' ';
jw.Indentation = 4;
jw.WriteRaw(config.ToString());
}
}
}
But that doesn't seem to have any effect: the file is still written with two space indentation. What am I doing wrong?
Upvotes: 21
Views: 13239
Reputation: 1
If you don`t have a class to serialize/deserialize your JSON object, you may use JObject from Newtonsoft.Json.Linq
var buildText = JObject.Parse(buildInfo.ToString());
File.WriteAllText(infoPath, buildText.ToString());
As a result you will have fully formatted .json file
Upvotes: -1
Reputation: 4255
I summarize the complete code, based on @Guffa's answer.
Changed from FileMode.OpenOrCreate
to FileMode.Create
. Otherwise the file will not be shortened when the new contents are smaller.
var config = JObject.Parse(File.ReadAllText("config.json"));
config["revision"] = 1;
using (FileStream fs = File.Open("config.json", FileMode.Create))
{
using (StreamWriter sw = new StreamWriter(fs))
{
using (JsonTextWriter jw = new JsonTextWriter(sw))
{
jw.Formatting = Formatting.Indented;
jw.IndentChar = ' ';
jw.Indentation = 4;
JsonSerializer serializer = new JsonSerializer();
serializer.Serialize(jw, config);
}
}
}
Upvotes: 0
Reputation: 18025
Here you have an extension method that makes json easy to read for human. It removes quotes in property names, converts enums to strings and indent json with 4 spaces.
public static string ToPrettyJson(this object obj)
{
var json = JsonConvert.SerializeObject(obj, Formatting.Indented, new StringEnumConverter());
json = Regex.Replace(json, @"^([\s]+)""([^""]+)"": ", "$1$2: ", RegexOptions.Multiline); // no quotes in props
json = Regex.Replace(json, @"^[ ]+", m => new String(' ', m.Value.Length * 2), RegexOptions.Multiline); // more indent spaces
return json;
}
Upvotes: -1
Reputation: 81
I ran into the same issue and found out that WriteRaw does not effect the indentation settings, however you can solve the issue using WriteTo on the JObject
using (FileStream fs = File.Open("config.json", FileMode.OpenOrCreate))
{
using (StreamWriter sw = new StreamWriter(fs))
{
using (JsonTextWriter jw = new JsonTextWriter(sw))
{
jw.Formatting = Formatting.Indented;
jw.IndentChar = ' ';
jw.Indentation = 4;
config.WriteTo(jw);
}
}
}
Upvotes: 8
Reputation: 100
Maybe try to feed a tab character to the IndentChar?
...
jw.IndentChar = '\t';
...
Accordinging to the documentation, it should use the tab character to indent the JSON instead of the space character. http://james.newtonking.com/json/help/index.html?topic=html/T_Newtonsoft_Json_Formatting.htm
Upvotes: 1
Reputation: 700650
The problem is that you are using config.ToString()
, so the object is already serialised into a string and formatted when you write it using the JsonTextWriter
.
Use a serialiser to serialise the object to the writer instead:
JsonSerializer serializer = new JsonSerializer();
serializer.Serialize(jw, config);
Upvotes: 16