禁用字典和列表的默认特殊处理?

时间:2016-09-12 15:05:51

标签: c# serialization json.net

我需要在json.net中禁用字典和列表的默认特殊处理。我不关心json的漂亮,我只需要一个功能正常的序列化/反序列化机制。具体来说,默认行为的问题是,如果类型实现IEnumerable或IDictionary,则不会序列化其他字段,并且字典键只是ToString'd而不是正确序列化。我正在替换序列化大量遗留对象的基础结构组件中的BinaryFormatter,因此重构所有这些对象以使用与默认json.net行为(属性,类型转换器等)兼容的机制将不仅是一个非常巨大的任务,而且在许多情况下,我认为甚至不可能。我尝试过这样的自定义合约解析器:

    private class ContractResolver : DefaultContractResolver
    {
        protected override JsonContract CreateContract(Type objectType)
        {
            var contract = base.CreateContract(objectType);
            if (contract is JsonDictionaryContract || contract is JsonArrayContract)
            {
                if (typeof(ISerializable).IsAssignableFrom(objectType))
                    contract = CreateISerializableContract(objectType);
                else
                    contract = CreateObjectContract(objectType);
            }
            return contract;
        }
    }

我希望这会有效地将这些类型更改回使用标准对象序列化行为,但是当我尝试使用此序列化一个简单字典时,我收到此错误

System.ArgumentException : Invalid type owner for DynamicMethod.
at System.Reflection.Emit.DynamicMethod.Init(String name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] signature, Type owner, Module m, Boolean skipVisibility, Boolean transparentMethod)
at System.Reflection.Emit.DynamicMethod..ctor(String name, Type returnType, Type[] parameterTypes, Type owner, Boolean skipVisibility)
at Newtonsoft.Json.Utilities.DynamicReflectionDelegateFactory.CreateDynamicMethod(String name, Type returnType, Type[] parameterTypes, Type owner)
at Newtonsoft.Json.Utilities.DynamicReflectionDelegateFactory.CreateParameterizedConstructor(MethodBase method)
at Newtonsoft.Json.Serialization.JsonObjectContract.set_ParametrizedConstructor(ConstructorInfo value)
at Newtonsoft.Json.Serialization.DefaultContractResolver.CreateObjectContract(Type objectType)

我不确定如何解决这个问题:)我有更好的方法吗?感谢任何帮助,谢谢!

更新 我在上面的代码中意识到,维护JsonArrayContract的实际数组类型(与所有IEnumerables相对)可能确实有意义,因为JsonObjectContracts不一定能够序列化本机数组也就不足为奇了,所以我改变了合同解析者如此:

if (contract is JsonDictionaryContract || (contract is JsonArrayContract && !objectType.IsArray))

现在会产生这个错误,而且我就像以前一样难倒

Newtonsoft.Json.JsonSerializationException : Cannot preserve reference to array or readonly list, or list created from a non-default constructor: System.Collections.Generic.KeyValuePair`2[System.Int32,System.Int32][]. Path '$values', line 1, position 311.
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateList(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue, String id)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ReadMetadataProperties(JsonReader reader, Type& objectType, JsonContract& contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue, Object& newValue, String& id)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateISerializableItem(JToken token, Type type, JsonISerializableContract contract, JsonProperty member)
at Newtonsoft.Json.Serialization.JsonFormatterConverter.Convert(Object value, Type type)
at System.Runtime.Serialization.SerializationInfo.GetValue(String name, Type type)
at System.Collections.Generic.Dictionary`2.OnDeserialization(Object sender)

0 个答案:

没有答案