C# System.Text.Json 或 Newtonsoft JSON 用于按属性进行序列化控制的属性标记

C# System.Text.Json or Newtonsoft JSON properties marking for serialization control by attributes

我只是想知道我是否可以通过任何属性标记 class 实例的某些 属性 并在序列化期间仅序列化那些标记的属性(当然,通过反序列化也仅影响通过标记的属性class 实例中的属性反之亦然 - 其余属性应保持不变...)。

我知道如何通过反射识别那些属性,但我不想自己再做一个Json序列化。

[MyFirstAttribute]
public string A { get; set; } = "hi";

[MyFirstAttribute]
public int B { get; set; } = 13;

[MySecondAttribute]
public string C { get; set; } = "something";

this link 中所述,您可以通过继承 JsonConverter class.

创建自定义 CustomJsonConverter

然后像这样使用它:

Employee employee = new Employee
{
    FirstName = "James",
    LastName = "Newton-King",
    Roles = new List<string>
    {
        "Admin"
    }
};

string json = JsonConvert.SerializeObject(employee, Formatting.Indented, new KeysJsonConverter(typeof(Employee)));

Console.WriteLine(json);

根据@ArgeKumandan 的建议:

public class KeysJsonConverter : JsonConverter
{
    private readonly Type[] _types;
    public KeysJsonConverter(params Type[] types) => _types = types;

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        JToken t = JToken.FromObject(value);
        if (t.Type != JTokenType.Object) t.WriteTo(writer);
        else
        {
            JObject jo = new JObject();
            foreach (PropertyInfo prop in value.GetType().GetProperties())
            {
                if (!prop.CanRead) continue;
                object propVal = prop.GetValue(value, null);
                if (propVal is null || !Attribute.IsDefined(prop, _types[0])) continue;
                    jo.Add(prop.Name, JToken.FromObject(propVal, serializer));
            }
        }
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException("Unnecessary because CanRead is false. The type will skip the converter.");
    }

    public override bool CanRead { get => false; }

    public override bool CanConvert(Type objectType) => _types.Any(t => t == _types[0]);
}

然后用法:

// serialization
var json = JsonConvert.SerializeObject(objectInstance1, Formatting.Indented, new KeysJsonConverter(typeof(MyFirstAttribute)));

// deserialization to an existing instance that updates just the properties contained in JSON
JsonConvert.PopulateObject(jsonCommon, objectInstance2);