构建默认情况下不会调用的自定义JSON序列化程序

时间:2017-05-31 23:58:46

标签: c# json serialization json.net

我使用Newtownsoft JSON.Net并希望添加自定义属性,然后使用JSONConverter处理这些自定义属性。目前,执行此操作的方法是[JsonConverter(typeof(CustomJsonConverter))]。但是我不希望这个转换器总是被调用,只有当我将它传递给JsonConvert.SerializeObject(...)时。这是因为这个类被两个不同的路径使用,其中一个路径需要根据属性修改JSON而另一个路径不需要。

换句话说,当我明确告诉我的代码考虑它们时,我只想要考虑这些属性。当Newtonsoft进行默认序列化时,应忽略它们。我怎样才能做到这一点?

示例:

class Foo {
    [CustomAttributeToAddMyExtraProperty]
    public int Bar;

    [JsonProperty('default')]
    public int Baz;
}

如果我只使用默认的Newtonsoft JSON.Net序列化,我应该

{
    "Bar":value1,
    "default":value2
}

但是如果我明确地传递我的自定义转换器,我应该得到这个:

{
    "Bar":value1,
    "default":value2,
    "MyExtraProperty":value3
}

请注意,始终使用JSON.Net属性。

更新

我试过这个:

namespace Project1
{
    class Class1
    {

        static void Main()
        {
            Class2 foo = new Class2();
            Console.WriteLine(JsonConvert.SerializeObject(foo, new JsonSerializerSettings() { ContractResolver = new BlahResolver() }));
            Console.Read();
        }
    }

    class Class2
    {
        [Blah]
        public int one = 1;

        [JsonProperty]
        public int two = 2;

        [Blah]
        public string three = "3";
    }

    internal class BlahAttribute : Attribute
    {
    }

    class BlahResolver : DefaultContractResolver
    {
        protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
        {
            JsonProperty property = base.CreateProperty(member, memberSerialization);
            var attr = property.AttributeProvider.GetAttributes(typeof(BlahAttribute), true);

            if (attr.Count == 1)
            {
                property.Converter = new BlahConverter();
            }
            return property;
        }
    }

    class BlahConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return objectType.IsValueType;
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            return existingValue;
        }

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            JToken token = JToken.Parse("{ \"foo\":\"a\", \"bar\":34 }");
            token.WriteTo(writer);
        }
    }
}

输出:

{"one":{"foo":"a","bar":34},"two":2,"three":{"foo":"a","bar":34}}

我能够使用自定义属性成功识别属性并将其重定向到我的自定义转换器。现在的问题是转换器正在添加属性,就像one是复杂类型一样。我想在顶级JSON中添加属性,而不是one的属性。

我想要的输出:

{"one":1, "foo":"a","bar":34,"two":2,"three":3,"foo":"a","bar":34}

我意识到这有多个具有相同名称的属性。我不知道这是否有效,但最终对象值将包含在名称中(例如one_fooone_bar),因此您可以忽略它。

2 个答案:

答案 0 :(得分:2)

通过您的更新,您非常接近获得此方案所需的工作。此时,您唯一的问题是在WriteJson方法中。

此时您需要做的只是:

writer.WritePropertyName("propertyName");
writer.WriteValue("propertyValue");

答案 1 :(得分:0)

如果您需要根据当前执行路径使用不同的序列化程序,那么属性路由不起作用是正确的

在序列化过程中传递当前所需的转换器:

string json = JsonConvert.SerializeObject(employee, Formatting.Indented, new MyCustomConverter(typeof(MyType)));

Source