如何控制JObject到字符串的序列化?
我有一些返回JObject的API,我通常会应用一些更改并保留或返回它们。我想避免持久化null属性并应用一些额外的格式,但JsonConvert似乎完全忽略了我的设置。
以下是问题的示例:
// startup.cs has the following
services.AddMvc().AddJsonOptions(o =>
{
o.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
});
public class SampleController : Controller
{
JsonSerializerSettings _settings = new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore
};
[HttpPost]
[Route("object")]
public object PostObject([FromBody] SomeObject data)
{
return JsonConvert.SerializeObject(data, _settings);
}
[HttpPost]
[Route("jobject")]
public object PostJObject([FromBody] JObject data)
{
return JsonConvert.SerializeObject(data, _settings);
}
public class SomeObject
{
public string Foo { get; set; }
public string Bar { get; set; }
}
}
发布{ "Foo": "Foo", "Bar": null }
:
/object
返回{"Foo":"Foo"}
/jobject
返回{"Foo":"Foo","Bar":null}
我希望JObject方法返回相同的输出json,就像我使用对象一样。如何在不创建助手的情况下实现这一目标?有没有办法使用相同的设置序列化JObject?
答案 0 :(得分:4)
我能够做到这一点的唯一方法是首先将JObject
转换为string
,然后将该字符串反序列化为ExpandoObject
(不要反序列化为{{1}因为你会得到一个object
)。 JObject
就像一个字典,它将导致ExpandoObject
实际调用配置的名称案例策略。我不确定为什么Newtonsoft.Json的作者没有像他们为字典类型那样处理JObject类型,但至少这项工作是有效的。
示例:
JsonConvert
我在这里使用// Construct a JObject.
var jObject = JObject.Parse("{ SomeName: \"Some value\" }");
// Deserialize the object into an ExpandoObject (don't use object, because you will get a JObject).
var payload = JsonConvert.DeserializeObject<ExpandoObject>(jObject.ToString());
// Now you can serialize the object using any serializer settings you like.
var json = JsonConvert.SerializeObject(payload, new JsonSerializerSettings
{
ContractResolver = new DefaultContractResolver
{
NamingStrategy = new CamelCaseNamingStrategy
{
// Important! Make sure to set this to true, since an ExpandoObject is like a dictionary.
ProcessDictionaryKeys = true,
}
}
}
);
Console.WriteLine(json); // Outputs: {"someName":"Some value"}
获取了这个技巧:JObject & CamelCase conversion with JSON.Net
答案 1 :(得分:3)
与NewtonSoft框架很好地集成的解决方案是提供一个自定义的JObject转换器,以兑现NamingStrategy
。
public class JObjectNamingStrategyConverter : JsonConverter<JObject> {
private NamingStrategy NamingStrategy { get; }
public JObjectNamingStrategyConverter (NamingStrategy strategy) {
if (strategy == null) {
throw new ArgumentNullException (nameof (strategy));
}
NamingStrategy = strategy;
}
public override void WriteJson (JsonWriter writer, JObject value, JsonSerializer serializer) {
writer.WriteStartObject ();
foreach (JProperty property in value.Properties ()) {
var name = NamingStrategy.GetPropertyName (property.Name, false);
writer.WritePropertyName (name);
serializer.Serialize (writer, property.Value);
}
writer.WriteEndObject ();
}
public override JObject ReadJson (JsonReader reader, Type objectType, JObject existingValue, bool hasExistingValue, JsonSerializer serializer) {
throw new NotImplementedException ();
}
}
var snakeNameStrategy = new SnakeCaseNamingStrategy ();
var jsonSnakeSettings = new JsonSerializerSettings {
Formatting = Formatting.Indented,
Converters = new [] { new JObjectNamingStrategyConverter (snakeNameStrategy) },
ContractResolver = new DefaultContractResolver {
NamingStrategy = snakeNameStrategy
},
};
var json = JsonConvert.SerializeObject (obj, jsonSnakeSettings);
您可以在GitHub上找到有效的PoC。
答案 2 :(得分:-6)
当序列化JObject
时,会写入原始JSON。 JsonSerializerSettings
不会影响其编写的JSON。