有没有办法在不更改格式的情况下修改 JSON?
Is there a way to modify JSON without changing the formatting?
使用 Newtonsoft.Json,您可以选择如何使用 JsonTextWriter
的 Formatting
枚举和属性来格式化 JSON。但是如果我从一个已经以某种方式格式化的 JSON 字符串开始并且我想修改它,有没有办法确保它保留其格式?
我能想到一些探索的途径:
- 是否有任何当前的 JSON 库可以在不反序列化的情况下就地修改 JSON 字符串?
- 反序列化 JSON 字符串时,有没有办法检测字符串的格式,以便在重新序列化时可以应用相同的格式?
- 是否有一个函数将反序列化的
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));
(我知道除了选择 Indented
或 None
之外,还有更多格式化 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,无论是否缩进,我相信这在以下前提下就足够了:
- 我们从客户端控制格式的变化
- 如果缩小,则格式更改为 Newtonsoft 的默认格式
- 假设它不能增长
- 如果转换保持字符串相同长度,则没有任何变化
当然,出现问题的情况如下:
- 收到 JSON 包含额外字符:
"First Name:"
,这在 Json 中有效,但在 Class 属性 名称中无效,因此您可能有一个担心的属性。
- JSON 仍然是一个字符串,可能会出现各种奇怪的东西,因此以任何程度的确定性对其进行验证都可能成为一场傻瓜竞赛(建立一个更好的傻瓜)
事实上,如果某些工具的目的是向人类展示数据:比 select 最清晰的格式(对我来说是缩进的)并始终显示。
如果设计通常是机器,则对最小有效载荷使用 none。我认为几乎所有习惯 JSON 的开发人员都希望将最小化的 JSON 作为有效负载。
使用 Newtonsoft.Json,您可以选择如何使用 JsonTextWriter
的 Formatting
枚举和属性来格式化 JSON。但是如果我从一个已经以某种方式格式化的 JSON 字符串开始并且我想修改它,有没有办法确保它保留其格式?
我能想到一些探索的途径:
- 是否有任何当前的 JSON 库可以在不反序列化的情况下就地修改 JSON 字符串?
- 反序列化 JSON 字符串时,有没有办法检测字符串的格式,以便在重新序列化时可以应用相同的格式?
- 是否有一个函数将反序列化的
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));
(我知道除了选择 Indented
或 None
之外,还有更多格式化 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,无论是否缩进,我相信这在以下前提下就足够了:
- 我们从客户端控制格式的变化
- 如果缩小,则格式更改为 Newtonsoft 的默认格式
- 假设它不能增长
- 如果转换保持字符串相同长度,则没有任何变化
当然,出现问题的情况如下:
- 收到 JSON 包含额外字符:
"First Name:"
,这在 Json 中有效,但在 Class 属性 名称中无效,因此您可能有一个担心的属性。 - JSON 仍然是一个字符串,可能会出现各种奇怪的东西,因此以任何程度的确定性对其进行验证都可能成为一场傻瓜竞赛(建立一个更好的傻瓜)
事实上,如果某些工具的目的是向人类展示数据:比 select 最清晰的格式(对我来说是缩进的)并始终显示。
如果设计通常是机器,则对最小有效载荷使用 none。我认为几乎所有习惯 JSON 的开发人员都希望将最小化的 JSON 作为有效负载。