You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无需Newtonsoft [JsonExtensionData]特性实现模型扩展数据可行吗?

不用[JsonExtensionData]实现额外JSON属性处理的方案

Hey there! Great question—yes, you absolutely can get the result you want without relying on Newtonsoft's [JsonExtensionData] attribute. The solution is to build a custom JsonConverter that manually handles any extra properties in your JSON, just like the attribute does. Let me walk you through a practical example.

核心思路

We'll create a converter that:

  • During deserialization: Maps known model properties first, then stores any unrecognized JSON keys/values into a dedicated collection (like a dictionary) in your model.
  • During serialization: Merges that collection of extra properties back into the final JSON output.

Step 1: Define Your Model

First, add a collection to your model to hold the extra properties (this replaces the [JsonExtensionData] attribute's storage):

public class YourModel
{
    // Your existing known properties
    public string ExpectedProperty1 { get; set; }
    public int ExpectedProperty2 { get; set; }

    // Collection to store extra JSON properties
    public Dictionary<string, object> ExtraProperties { get; set; } = new Dictionary<string, object>();
}

Step 2: Implement the Custom JsonConverter

This converter will handle the heavy lifting of moving extra properties between JSON and your model:

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Reflection;

public class YourModelConverter : JsonConverter<YourModel>
{
    public override YourModel ReadJson(JsonReader reader, Type objectType, YourModel existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        var model = existingValue ?? new YourModel();
        var jsonObject = JObject.Load(reader);

        // First, populate the known model properties
        serializer.Populate(jsonObject.CreateReader(), model);

        // Then, add any unrecognized properties to ExtraProperties
        foreach (var jsonProperty in jsonObject.Properties())
        {
            var modelProperty = model.GetType().GetProperty(
                jsonProperty.Name, 
                BindingFlags.Public | BindingFlags.Instance
            );
            
            if (modelProperty == null)
            {
                model.ExtraProperties[jsonProperty.Name] = jsonProperty.Value.ToObject<object>(serializer);
            }
        }

        return model;
    }

    public override void WriteJson(JsonWriter writer, YourModel value, JsonSerializer serializer)
    {
        // Convert the model to a JObject (includes known properties)
        var jsonObject = JObject.FromObject(value, serializer);

        // Add all extra properties from the dictionary to the JObject
        foreach (var extraProp in value.ExtraProperties)
        {
            jsonObject.Add(extraProp.Key, JToken.FromObject(extraProp.Value, serializer));
        }

        // Write the final combined JSON
        jsonObject.WriteTo(writer);
    }
}

Step 3: Use the Converter

You have two ways to enable this converter:

Option 1: Attribute the Model

Mark your model with the converter so it's used automatically:

[JsonConverter(typeof(YourModelConverter))]
public class YourModel
{
    // ... your properties ...
}

Option 2: Specify During Serialization/Deserialization

Add the converter to your JsonSerializerSettings when you call the Newtonsoft methods:

var settings = new JsonSerializerSettings();
settings.Converters.Add(new YourModelConverter());

// Deserialize JSON to your model
var model = JsonConvert.DeserializeObject<YourModel>(yourInputJson, settings);

// Serialize the model back to JSON (includes extra properties)
var outputJson = JsonConvert.SerializeObject(model, settings);

Customization Tips

  • If you know all extra properties will be a specific type (e.g., strings), replace Dictionary<string, object> with Dictionary<string, string> and adjust the ToObject call accordingly.
  • If you don't want a public ExtraProperties property, you can make it private and adjust the converter to access it via reflection (though public is simpler for most cases).

内容的提问来源于stack exchange,提问作者LEspera

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 08:57:36