【问题标题】:Is there a way to control which fields are serialized programmatically using JSON.Net?有没有办法控制使用 JSON.Net 以编程方式序列化哪些字段?
【发布时间】:2022-02-25 20:59:18
【问题描述】:

给定 3rd 方库中的变体样式类,编码如下:

enum VariantType
{
   Type1,
   Type2,
   ... etc
   TypeN
}

class Variant
{
    [SerializeField]
    private VariantType _variantType;
    public VariantType VariantType => _variantType;


    [SerializeField] // Unity Serialization attribute
    private Type1 _type1;
    public Type1 Type1 => _type1;

    ... etc

    [SerializeField] // Unity Serialization attribute
    private TypeN _typeN;
    public TypeN TypeN => _typeN;
}

有没有办法使用 JSON.Net 在序列化 Variant 时仅序列化 VariantType 标识的单个属性?

所以我们得到

{
   "_variantType": "Type1",
   "_type1": {...}
}

而不是(假设没有任何属性为空)

{
   "_variantType": "Type1",
   "_type1": {...}
...
   "_typeN": {...}
}

我使用自定义 ContractResolver 和 CreateProperty 进行了调查,但似乎没有访问父对象的方法。

【问题讨论】:

标签: c# json.net


【解决方案1】:

使用Linq 2 JSON,您可以执行以下操作:

//Parse your json as JObject
var json = "{\"_variantType\": \"Type1\",\"_type1\": {},\"_type2\": {},\"_typeN\": {}}";
var semiParsedJson = JObject.Parse(json);

//Retrieve the variant type
var variantTypeNode = semiParsedJson["_variantType"];
var variantType = variantTypeNode.ToString();

//Construct the type name from the variant type then retrieve it
var typeNodeName = $"_{char.ToLower(variantType[0])}{variantType.Substring(1)}";
var typeNode = semiParsedJson[typeNodeName];

//Create a new object to add there the retrieved tokens' parents
var rootObject = new JObject();
rootObject.Add(variantTypeNode.Parent);
rootObject.Add(typeNode.Parent);

rootObject 上调用ToString 会发出这个

{
  "_variantType": "Type1",
  "_type1": {}
}

【讨论】:

  • @Phil 请告诉我你的结论是什么。 :)
【解决方案2】:

事实证明我错了,可以从 ContractResolver 访问父对象。我的答案是扩展我已经拥有的 ContractResolver。见https://www.newtonsoft.com/json/help/html/ContractResolver.htm

        protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
        {
            JsonProperty property = base.CreateProperty(member, memberSerialization);
            if (property.DeclaringType == typeof(Variant))
            {
                property.ShouldSerialize =
                    instance =>
                    {
                        Variant e = (Variant)instance;

                        switch (property.PropertyName)
                        {
                            case "_type1":
                                return e.Type == VariantType.Type1;
 ... etc

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-18
    • 2014-06-02
    • 1970-01-01
    • 2016-03-04
    • 2010-09-09
    相关资源
    最近更新 更多