3

After writing the JSON into the file using

File.WriteAllText(fileName, JsonConvert.SerializeObject(jsonToWrite, Formatting.Indented)). 

I am getting a tailing space after every ":". How to avoid it?

Current in red, expected in Green enter image description here

eoeo
  • 235
  • 2
  • 13
  • What's wrong about it? Not sure if there is an option for this, at all. – Fildor Jul 29 '21 at 06:42
  • 2
    I'm not sure you can. It looks like it's fairly hard-coded into the library. See the code [here](https://github.com/JamesNK/Newtonsoft.Json/blob/52e257ee57899296d81a868b32300f0b3cfeacbe/Src/Newtonsoft.Json/JsonWriter.cs#L881-L886). – ProgrammingLlama Jul 29 '21 at 06:42
  • 5
    question: what's the problem with it? _no_ JSON parsing library should have trouble with whitespaces – Franz Gleichmann Jul 29 '21 at 06:42
  • 1
    If you absolutely insist, you could replace all `": "` by `":"` in the resulting string. But meh ... – Fildor Jul 29 '21 at 06:44
  • @Fildor more like `": "` -> `":"` (with quotes) to reduce the risk of modifying the keys/values. – abdusco Jul 29 '21 at 06:44
  • @abdusco That's what I wrote, didn't I? – Fildor Jul 29 '21 at 06:45
  • I have to change one field in the json. As I rewrite the file, during git diff all the lines would change due to whitespace. – eoeo Jul 29 '21 at 06:46
  • 1
    @Fildor True, but it was a bit ambiguous :) – abdusco Jul 29 '21 at 06:46
  • 5
    @eoeo But surely once you do it one time, in future it will have those spaces and thus not be a problem? – ProgrammingLlama Jul 29 '21 at 06:46
  • 1
    _"As I rewrite the file, during git diff all the lines would change due to whitespace."_ - only once. ;) – Fildor Jul 29 '21 at 06:46
  • 1
    @abdusco It's a terrible idea anyway and I already regret having suggested it. – Fildor Jul 29 '21 at 06:47
  • Does this answer your question? [Configure vscode json formatting spaces](https://stackoverflow.com/questions/42120299/configure-vscode-json-formatting-spaces) – Bizhan Jul 29 '21 at 06:49
  • @Llama yeah you are right! but is there a way to do this other than replace? coz I have to modify a various files :( – eoeo Jul 29 '21 at 06:52
  • @Bizhan no, I want the source to be changed – eoeo Jul 29 '21 at 06:53
  • 1
    `I have to change one field in the json. As I rewrite the file, during git diff all the lines would change due to whitespace.` ?w=1 in github to ignore whitespace. – mjwills Jul 29 '21 at 06:56
  • 3
    Then don't commit lines that only have whitespace changes? https://handyman.dulare.com/git-tips-and-tricks-for-every-day-usage/ – Jeremy Lakeman Jul 29 '21 at 07:11

2 Answers2

0

The code that adds the space is located in JsonTextWriter.WriteIndentSpace, and is called by the standard JsonWriter.

One possible option is to write your own JsonTextWriter derived class, override WriteIndentSpace and do nothing in it.

class MyWriter : JsonTextWriter
{
    public MyWriter(TextWriter sw) : base(sw)
    { }

    protected override void WriteIndentSpace()
    { }
}

You then need to write custom serialization code to actually use this writer

    static string Convert(object value, JsonSerializerSettings settings)
    {
        JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings);
        StringBuilder sb = new StringBuilder(256);
        StringWriter sw = new StringWriter(sb, CultureInfo.InvariantCulture);
        using (var jsonWriter = new MyWriter(sw))
        {
            jsonWriter.Formatting = jsonSerializer.Formatting;

            jsonSerializer.Serialize(jsonWriter, value, null);
        }

        return sw.ToString();
    }

You can then call it with whatever settings you want, and an IndentSpace will never be inserted.

var json = Convert(myObject, new JsonSerializerSettings{ Formatting = Formatting.Indented });

Some of the code could be simplified if you know exactly what settings you want to use every time.

dotnetfiddle

Charlieface
  • 52,284
  • 6
  • 19
  • 43
-3

Replace ": " by ":" in json content with string.Replace

string fileName = "file.txt";
string jsonFromSerialization = "{\n\t\"foo\": \"bar\",\n\t\"bar\": \"foo\"\n}"; //JsonConvert.SerializeObject
jsonFromSerialization = jsonFromSerialization.Replace("\": \"", "\":\"");
File.WriteAllText(fileName, jsonFromSerialization);

Replace "<any number of whitespaces>:<any number of whitespaces>"
eg. " : " by ":" in json content with Regex.Replace

string fileName = "file.txt";
string jsonFromSerialization = "{\n\t\"foo\"     :     \"bar\",\n\t\"bar\"    :  \"foo\"\n}"; //JsonConvert.SerializeObject
string pattern = "\"\\s*:\\s*\"";
jsonFromSerialization = Regex.Replace(jsonFromSerialization, pattern, "\":\"");
File.WriteAllText(fileName, jsonFromSerialization);

Result
file


Another approach. Thanks to Jon Skeet for his suggestion. In this example validates special strings in the value of a key.

eg.

{"foo":   "xyz\": ","bar"    :  "foo"}

Code

string JsonReplace(string json)
{
    string pattern = @"(\s*""\w+"")\s*:\s*";
    foreach (Match m in Regex.Matches(json, pattern))
    {
        json = json.Replace(m.Value, m.Value.Replace(" ", string.Empty));
    }
    return json;
}

string fileName = "file.txt";
var data = new
{
    foo = "xyz\": ",
    bar = "foo"
};
string jsonFromSerialization = JsonConvert.SerializeObject(data);
jsonFromSerialization = JsonReplace(jsonFromSerialization);
File.WriteAllText(fileName, jsonFromSerialization);

Result
result

Joma
  • 3,520
  • 1
  • 29
  • 32
  • 1
    Note that this won't work for anything other than string values, leading to inconsistent formatting. It feels *really* fragile, too - fundamentally, messing with the string representation of JSON, XML etc after generation is rarely a good idea IMO. – Jon Skeet Jul 29 '21 at 07:34
  • 1
    Example of how it's brittle... if you have a string value of `xyz": `, the JSON representation would be `"xyz\": "`... which this replacement will change to `"xyz\":"`. – Jon Skeet Jul 29 '21 at 07:37
  • You are correct, but your example is very very specific, placing json within the value of a key which is a bit far-fetched. It's something that the developer may not need to solve -> Json inside the json. – Joma Jul 29 '21 at 07:57
  • 1
    No, it doesn't have to be JSON within JSON. It's just a string that ends with a double quote, colon, space. That's not JSON-specific - it's just a string. But fundamentally it shows how fragile this is. (And then there's the "only working with string values" aspect too, of course.) It's an approach I'd strongly recommend against. – Jon Skeet Jul 29 '21 at 08:12
  • And does it handle the key itself having colons and quotes? (Rare, but entirely valid - and feasible if you're serializing a `Dictionary`.) I'd need to look really, really carefully to try to validate this - which would alarm me, because it's so easy to go wrong. As per the comment thread on the question itself, I think a far better solution is just *not to do this at all*. – Jon Skeet Jul 29 '21 at 09:15