C#学习教程:Newtonsoft.JSON无法使用TypeConverter属性转换模型最近我收到一个请求,要在MySQL数据库字段中存储一个JSON字符串,通过Newtonsoft.Json转换为C#对象,所以我决定实现一个TypeConverter来将JSON字符串转换为自定义C#模型。不幸的是,当TypeConverter属性添加到我的C#模型时,我无法在我的解决方案中的任何地方使用以下命令来反序列化我的JSON字符串:JsonConvert.DeserializeObject(json);删除属性确实解决了问题,但这阻止了我将MySQL数据库字段转换为自定义C#对象。这是我的C#模型,添加了TypeConverter属性:usingSystem.ComponentModel;[TypeConverter(typeof(FooConverter))]publicclassFoo{publicboola{get;放;}publicboolb{得到;放;}publicboolc{得到;放;}publicFoo(){}}这是我的TypeConverter类:使用Newtonsoft.Json;使用系统;使用System.ComponentModel;公共类FooConverter:TypeConverter{publicoverrideboolCanConvertFrom(ITypeDescriptorContextcontext,System.TypesourceType){if(sourceType==typeof(string)){}returnbase.CanConvertFrom(context,sourceType);}publicoverrideobjectConvertFrom(ITypeDescriptorContextcontext,System.Globalization.CultureInfoculture,objectvalue){if(valueisstring){strings=value.ToString().Replace("\","");Foof=JsonConvert.DeserializeObject(s);返回f;}returnbase.ConvertFrom(context,culture,value);一旦我将属性添加到Foo类,我得到以下错误:要正确反序列化的JSON字符串值。要修复此错误,请将JSON更改为JSON字符串值或更改反序列化类型,使其成为普通的.NET类型(例如,不是像整数这样的原始类型,也不是像数组或列表这样的集合类型),这可以从JSON对象反序列化。JsonObjectAttribute也可以添加到类型以强制它从JSON对象反序列化。我使用以下字符串(无需添加TypeConverter属性即可完美运行):"{"Foo":{"a":true,"b":false,"c":false}}"不确定这里发生了什么什么,有任何想法吗?太感谢了!!!更新我发现我在接受带有Foo作为属性的测试类的MVCAPI控制器上的操作,或者在向Foo类添加TypeConverter属性时接受Foo作为对象的控制器上的操作也有问题。下面是一个有问题的测试控制器的例子:t.Foo;}AcceptVerbs("POST","GET")]publicvoidPostFooObj(Foof){//Foo类中添加TypeConverter属性时返回nullreturnf;当上述任一操作通过AJAX接收具有以下结构的JSON时,TypeConverter可能会导致重写WebAPI模型绑定修复问题并返回null://eg.PostTestClass(TestClassT){'Foo':{'a':false,'b':真,'c':假}};//eg.PostFooObj(Foof){'a':false,'b':true,'c':false}在Foo类中添加TypeConverter属性时,只要找到路径就会调用下面的方法在FooConverterTypeConverter类上:publicoverrideboolCanConvertFrom(ITypeDescriptorContextcontext,System.TypesourceType){if(sourceType==typeof(string)){returntrue;}returnbase.CanConvertFrom(context,sourceType);}FooConverterTypeControllerApiController的操作未调用ConvertFrom方法,这可能是问题的原因。同样,这是一个类似的情况,控制器操作在没有TypeConverter属性的情况下也能正常工作。太感谢了!!非常感谢。这里发生了一些事情。首先,一个初步问题:即使没有应用TypeConverter,您的JSON也不对应于您的类Foo,它对应于一些包含Foo属性的容器类,例如:publicclassTestClass{publicFooFoo{get;放;}}即给定您的JSON字符串,以下将不起作用:varjson="{"Foo":{"a":true,"b":false,"c":false}}";varfoo=JsonConvert。反序列化对象(json);但以下将:vartest=JsonConvert.DeserializeObject(json);我怀疑这只是问题中的一个错误,所以我假设您要反序列化一个包含属性Foo的类。您看到的主要问题是Json.NET将尝试使用TypeConverter(如果存在)将正在序列化的类转换为JSON字符串。来自文档:PrimitiveTypes.Net:TypeConverter(convertibletoString)JSON:String但是在你的JSON中,Foo不是JSON字符串,它是一个JSON对象,所以一旦应用了类型转换器,反序列化就会失败。嵌入的字符串如下所示:{"Foo":"{"a":true,"b":false,"c":false}"}注意所有引号是如何转义的。即使您更改Foo对象的JSON格式以匹配它,您的反序列化仍然会失败,因为TypeConverter和Json.NET会尝试递归地相互调用。因此,您需要做的是全局禁用Json.NET对TypeConverter的使用并回退到默认序列化,同时在所有其他情况下保留TypeConverter使用。这有点棘手,因为没有可应用于禁用类型转换器的Json.NET属性,而是需要一个特殊的合同解析器和一个特殊的JsonConverter才能使用它:();类NoTypeConverterContractResolver:DefaultContractResolver{protectedoverrideJsonContractCreateContract(TypeobjectType){if(typeof(T).IsAssignableFrom(objectType)){varcontract=this.CreateObjectContract(objectType);contract.Converter=null;//同时清空转换器以防止无限递归。退货合同;}returnbase.CreateContract(objectType);}}publicoverrideboolCanConvert(TypeobjectType){returntypeof(T).IsAssignableFrom(objectType);}publicoverrideobjectReadJson(JsonReaderreader,TypeobjectType,objectexistingValue,JsonSerializerserializer){returnJsonSerializer.CreateDefault(newJsonSerializerSettings{ContractResolver=resolver}).Deserialize(reader,objectType);}公共overridevoidWriteJson(JsonWriterwriter,objectvalue,JsonSerializerserializer){JsonSerializer.CreateDefault(newJsonSerializerSettings{ContractResolver=resolver}).Serialize(writer,value);}}}并使用它像:[TypeConverter(typeof(FooConverter))][JsonConverter(typeof(NoTypeConverterJsonConverter))]publicclassFoo{publicboola{get;放;}publicboolb{得到;放;}publicboolc{得到;放;}publicFoo(){}}publicclassFooConverter:TypeConverter{publicoverrideboolCanConvertFrom(ITypeDescriptorContextcontext,System.TypesourceType){if(sourceType==typeof(string)){返回真;}returnbase.CanConvertFrom(context,sourceType);}publicoverrideobjectConvertFrom(ITypeDescriptorContextcontext,System.Globalization.CultureInfoculture,objectvalue){if(valueisstring){strings=value.ToString();//s=s.Replace("\","");Foof=JsonConvert.DeserializeObject(s);返回f;}返回base.ConvertFrom(上下文,cul真实,价值);}}示例Fiddle最后,您可能还应该在类型转换器中实现ConvertTo方法,请参阅如何:实现类型转换器。避免这种行为的一种简单方法是从转换检查中删除OR,即删除||destinationType==typeof(string)下面的例子..publicclassDepartmentBindModelConverter:TypeConverter{//删除了||destinationType==typeof(string),允许newtonsoftjson转换具有typeconverter属性的模型if(destinationType==typeof(DepartmentViewModel)&&valueisDepartmentBindModel){vardepartment=(DepartmentBindModel)value;returnnewDepartmentViewModel{Id=department.Id,Name=department.Name,GroupName=department.GroupName,ReturnUrl=department.ReturnUrl};}returnbase.ConvertTo(context,culture,value,destinationType);如果你有一个结构而不是一个类,当试图(反)序列化一个Nullable时,接受的答案仍然会进入无限递归,避免修改CreateContract,如下图:以上为C#学习教程:Newtonsoft.JSON不能使用TypeConverter属性转换模型共享的所有内容。如果对大家有用,需要进一步了解C#学习教程,希望大家多多关注——protectedoverrideJsonContractCreateContract(TypeobjectType){if(typeof(T).IsAssignableFrom(objectType)||Nullable.GetUnderlyingType(objectType)!=null&&typeof(T).IsAssignableFrom(Nullable.GetUnderlyingType(objectType))){varcontract=this.CreateObjectContract(objectType);contract.Converter=null;//同时清空转换器以防止无限递归。退货合同;}returnbase.CreateContract(objectType);}本文收集自网络,不代表立场,如涉及侵权,请点击右边联系管理员删除。如需转载请注明出处:
