如何使用Json.NET以与对象相同的方式序列化JObject?

时间:2016-10-25 15:49:50

标签: c# json.net

如何控制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?

3 个答案:

答案 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

JObject自定义转换器

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。