【问题标题】:How to avoid the tailing space space after ":" in using Newtonsoft使用Newtonsoft如何避免“:”后的拖尾空间空间
【发布时间】:2021-10-04 20:00:30
【问题描述】:

将 JSON 写入文件后使用

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

每个“:”后都有一个尾随空格。如何避免?

当前为红色,预计为绿色

【问题讨论】:

  • 我不确定你可以。看起来它是相当硬编码到库中的。见代码here
  • 问题:它有什么问题? no JSON 解析库应该有空格问题
  • 如果您绝对坚持,您可以将结果字符串中的所有": " 替换为":"。但是嗯...
  • @eoeo 但是一旦你做了一次,将来肯定会有这些空间,因此不是问题吗?
  • 那么不要提交只有空格更改的行? handyman.dulare.com/git-tips-and-tricks-for-every-day-usage

标签: c# json.net


【解决方案1】:

将 json 内容中的 ": " 替换为 ":"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);

替换"<any number of whitespaces>:<any number of whitespaces>"
例如。 " : " 通过“:”在带有Regex.Replace的json内容中@

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);

结果


另一种方法。感谢Jon Skeet 的建议。 在此示例中验证键值中的特殊字符串。

例如。

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

代码

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);

结果

【讨论】:

  • 请注意,这不适用于字符串值以外的任何内容,从而导致格式不一致。它也感觉真的很脆弱 - 从根本上说,在生成之后弄乱 JSON、XML 等的字符串表示形式很少是 IMO 的好主意。
  • 它的脆弱性示例...如果您的字符串值为xyz": ,则JSON 表示将为"xyz\": "...此替换将更改为"xyz\":"。跨度>
  • 你是对的,但你的例子非常具体,将 json 放在一个有点牵强的键的值中。这是开发者可能不需要解决的问题 -> json里面的Json。
  • 不,它不必是 JSON 中的 JSON。它只是一个以双引号、冒号、空格结尾的字符串。这不是 JSON 特定的 - 它只是一个字符串。但从根本上说,它表明这是多么脆弱。 (当然,还有“仅使用字符串值”方面。)这是我强烈反对的一种方法。
  • 它是否处理带有冒号和引号的密钥本身? (很少见,但完全有效 - 如果您要序列化 ​​Dictionary<string, string>,并且可行。)我需要非常非常仔细地尝试验证这一点 - 这会让我感到震惊,因为它很容易出错。根据问题本身的评论线程,我认为更好的解决方案是根本不这样做
【解决方案2】:

添加空格的代码位于JsonTextWriter.WriteIndentSpace,由标准JsonWriter调用。

一种可能的选择是编写自己的JsonTextWriter 派生类,覆盖WriteIndentSpace 并且在其中什么都不做。

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

    protected override void WriteIndentSpace()
    { }
}

然后您需要编写自定义序列化代码才能实际使用此编写器

    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();
    }

然后您可以使用任何您想要的设置调用它,并且永远不会插入 IndentSpace

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

如果您确切知道每次要使用哪些设置,则可以简化一些代码。

dotnetfiddle

【讨论】:

    猜你喜欢
    • 2016-02-18
    • 2011-09-21
    • 2021-03-07
    • 2011-10-31
    • 2011-08-16
    • 1970-01-01
    • 2013-11-14
    • 2013-03-17
    • 1970-01-01
    相关资源
    最近更新 更多