有没有办法在不更改格式的情况下修改 JSON?

Is there a way to modify JSON without changing the formatting?

使用 Newtonsoft.Json,您可以选择如何使用 JsonTextWriterFormatting 枚举和属性来格式化 JSON。但是如果我从一个已经以某种方式格式化的 JSON 字符串开始并且我想修改它,有没有办法确保它保留其格式?

我能想到一些探索的途径:

  1. 是否有任何当前的 JSON 库可以在不反序列化的情况下就地修改 JSON 字符串?
  2. 反序列化 JSON 字符串时,有没有办法检测字符串的格式,以便在重新序列化时可以应用相同的格式?
  3. 是否有一个函数将反序列化的 JObject 与它来自的 JSON 字符串结合起来,以便将对象的更改应用于旧字符串之上而不是用于构建新字符串?

问题示例:

var obj = JObject.Parse(json);
obj["foo"] = "bar";

Console.WriteLine(obj.ToString(Formatting.Indented));
// {
//   "baz": "qux",
//   "foo": "bar"
// }

Console.WriteLine(obj.ToString(Formatting.None));
// {"baz":"qux","foo":"bar"}

// Not knowing how the input was formatted,
// how can I know what options to use?

解决方案可能是这样的:

var format = JsonConvert.GetFormat(json); // No such method?
var obj = JObject.Parse(json);
obj["foo"] = "bar";

Console.WriteLine(obj.ToString(format));

(我知道除了选择 IndentedNone 之外,还有更多格式化 JSON 的方法,但为了清楚起见,我让示例保持简单。)

我认为:这可能是徒劳的追求。

虽然它是人类可读的,但很少有人阅读。事实上,我更担心不小心将重要的东西解析进出有效对象。

但是,为了在 Newtonsoft 中获得一点乐趣,如果在原始缩进时没有缩进的情况下进行格式化,则此方法有效。

var person = new Person()
    {
        Name = "John",
        Colors = new List<string>() {"Red", "Blue","Green"}
    };

    var rawJson = Newtonsoft.Json.JsonConvert.SerializeObject(person, Formatting.Indented);     
    var newJson = Newtonsoft.Json.JsonConvert.SerializeObject(person, Formatting.None);

    var settings =  new Newtonsoft.Json.JsonSerializerSettings();
    settings.Formatting = (Formatting)(newJson.Length <= rawJson.Length ? 1 : 0);       

    var finalJson = JsonConvert.SerializeObject(person, settings);

如果我们只关心 Newtonsoft,无论是否缩进,我相信这在以下前提下就足够了:

  1. 我们从客户端控制格式的变化
  2. 如果缩小,则格式更改为 Newtonsoft 的默认格式
  3. 假设它不能增长
  4. 如果转换保持字符串相同长度,则没有任何变化

当然,出现问题的情况如下:

  1. 收到 JSON 包含额外字符:"First Name:",这在 Json 中有效,但在 Class 属性 名称中无效,因此您可能有一个担心的属性。
  2. JSON 仍然是一个字符串,可能会出现各种奇怪的东西,因此以任何程度的确定性对其进行验证都可能成为一场傻瓜竞赛(建立一个更好的傻瓜)

事实上,如果某些工具的目的是向人类展示数据:比 select 最清晰的格式(对我来说是缩进的)并始终显示。

如果设计通常是机器,则对最小有效载荷使用 none。我认为几乎所有习惯 JSON 的开发人员都希望将最小化的 JSON 作为有效负载。