簡體   English   中英

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

[英]How to serialize a JObject the same way as an object with 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?

我能夠做到這一點的唯一方法是首先將JObject轉換為string ,然后將該字符串反序列化為ExpandoObject (不要反序列化為object因為你將返回一個JObject )。 ExpandoObject就像一個字典,它將使JsonConvert實際調用配置的名稱案例策略。 我不確定為什么Newtonsoft.Json的作者沒有像他們為字典類型那樣處理JObject類型,但至少這項工作是有效的。

例:

// 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"}

我在這里使用ExpandoObject獲取技巧:使用JSON.Net進行JObject和CamelCase轉換

與NewtonSoft框架完美集成的解決方案是提供一個尊重NamingStrategy的自定義JObject轉換器。

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。

當一個JObject被序列化時,它的原始JSON被寫入。 JsonSerializerSettings不影響其編寫的JSON。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM