自定义Newtonsoft.Json在单独的库中序列化对象

时间:2015-07-07 13:32:56

标签: c# json serialization

我想为控制器编写一个自定义的json序列化程序,当它遇到一个非原语(不包括字符串/日期时间)时,它会在该对象中查找ID字段/属性,然后不是序列化整个对象,而是编写一个{ID,Name}(其中ID是ID的值,Name是数据对象的名称)。

这背后的目的是我编写一个缓存查看器,但缓存项可能会变得很大。我可以使用ID字段并忽略UI中的其余部分,但随后我可能会遇到在响应中发送大量数据的问题。

我无法弄清楚我应该从哪里开始,所以请原谅这个问题,如果它有点广泛。

额外备注: 我需要序列化的数据项在一个单独的库中,我无法访问它们,但我保证它们都将使用ID字段。如果我错过了一些数据点,这是可以的,因为它们是非原始的,非日期时间,非字符串字段。

这是我到目前为止只写原语:

public class FieldsOnlyFormatterConfig : Attribute, IControllerConfiguration
    {
        public void Initialize(HttpControllerSettings settings,
            HttpControllerDescriptor descriptor)
        {
            // Clear the formatters list.
            settings.Formatters.Clear();
            var formatter = new JsonMediaTypeFormatter();
            formatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
            formatter.SerializerSettings.ContractResolver = new CustomResolver();
            // Add a custom media-type formatter.
            settings.Formatters.Add(formatter);
        }


    }

    class CustomResolver : DefaultContractResolver
    {
        protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
        {
            JsonProperty prop = base.CreateProperty(member, memberSerialization);

            if (member.MemberType == MemberTypes.Field && (prop.PropertyType.IsPrimitive || prop.PropertyType == typeof(string)))
            {
                prop.ShouldSerialize = obj => true;
            }
            else
            {
                prop.ShouldSerialize = obj => false;
            }

            return prop;
        }
    }

1 个答案:

答案 0 :(得分:0)

因此,随着一些更多的摆弄,我能够弄清楚如何完成我想要的。

我更改了自定义解析程序以检测我的属性类型是否为DataItem,然后将prop.Converter设置为使用自定义jsonConverter:

class CustomResolver : DefaultContractResolver
    {
        protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
        {
            JsonProperty prop = base.CreateProperty(member, memberSerialization);

            if (member.MemberType == MemberTypes.Field && (prop.PropertyType.IsPrimitive || prop.PropertyType == typeof(string)))
            {
                prop.ShouldSerialize = obj => true;
            }
            else if (prop.PropertyType.IsSubclassOf(typeof(DataItem)))
            {
                prop.ShouldSerialize = obj => true;
                prop.Converter = new DataItemConverter();
            }
            else
            {
                prop.ShouldSerialize = obj => false;
            }

            return prop;
        }
    }

在自定义json转换器中,在WriteJson上我将对象转换为DataItem(一个我知道我想要的所有内容的类,其中有“id”字段我正在寻找)然后做了一些自定义写入:

class DataItemConverter: JsonConverter
    {

        public override bool CanConvert(Type objectType)
        {
            return true;
        }

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

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            var di = value as DataItem;
            writer.WriteStartObject();
            writer.WritePropertyName("id");
            writer.WriteValue(di.Id);
            writer.WriteEndObject();
        }
    }