当前位置: 首页 > 编程语言 > C#

使用JSON.Net共享字典中复杂类型的特定用法序列化

时间:2023-04-10 16:30:54 C#

使用JSON.Net字典中复杂类型的特定用法序列化我上了一堂课publicclassMyValue{publicStringProp1{get;放;}publicStringProp2{得到;放;我将其用作普通属性和字典键的类型。我需要的是这样一种方式,当这个类被用作属性时,它被序列化为{"Prop1":"foo","Prop2":"bar"}但是当它被用作字典键时,它的序列化是以JSON.Net能够正确反序列化的方式完成。将ToString()方法添加到MyValue时,我能够创建允许用作字典键的文本表示形式(不是JSON),但不幸的是,之后我无法反序列化它。即使为MyValue添加JsonConverter也无济于事,因为它似乎无法将非JSON作为源格式处理(另外,当序列化为属性时,它是json,因此转换器需要以某种方式处理它们).你可以做的是在代理KeyValuePair数组中序列化和反序列化你的字典,如下所示:}[DataMember]public}[IgnoreDataMember]publicDictionaryDictionary{get;放;}[DataMember(Name="Dictionary")]privateKeyValuePair[]SerializedDictionary{get{if(Dictionary==null)returnnull;返回字典.ToArray();}set{if(value==null){Dictionary=null;}else{Dictionary=value.ToDictionary(pair=>pair.Key,pair=>pair.Value);}}}}(这里我使用的是DataContract属性,但我可以很容易地使用[JsonIgnore]和[JsonProperty("Dictionary")])所以,为了测试这个(假设你已经正确地覆盖了GetHashCode()和Equals(),你需要这样做才能将它用作字典键),我做了以下操作:字典[(新我的价值(“A”,“A”))]=1;字典[(新我的价值(“B”,“B”))]=2;varmyContainer=newMyContainer(){MyValue=newMyValue("AProperty","At顶层"),Dictionary=dict};varjson=JsonConvert.SerializeObject(myContainer,Formatting.Indented);Debug.WriteLine(json);try{varnewContainer=JsonConvert.DeserializeObject(json);}catch(Exceptionex){Debug.Assert(false,ex.ToString());//没有断言-没有抛出异常。}try{vardictjson=JsonConvert.SerializeObject(dict,Formatting.Indented);Debug.WriteLine(dictjson);varnewDict=JsonConvert.DeserializeObject>(dictjson);}catch(Exceptionex){Debug.WriteLine("Caughtexpectedexceptiondeserializingdictionarydirectly:"+ex.ToString());}}}果然反序列化没有异常container,但是字典是直接反序列化的并为容器创建了以下JSON:{"MyValue":{"Prop1":"AProperty","Prop2":"Atthetoplevel"},"Dictionary":[{"Key":{"Prop1":"A","Prop2":"A"},"Value":1},{"Key":{"Prop1":"B","Prop2":"B"},"Value":2}]}那是你要的吗?更新或者,如果您不喜欢代理数组,您可以将以下JsonConverterAttribute应用于每个Dictionary属性以获得相同的结果:}publicMyValueMyValue{得到;放;}[JsonConverter(typeof(DictionaryToArrayConverter))]publicDictionaryDictionary{get;放;}}publicclassDictionaryToArrayConverter:JsonConverter{publicoverrideboolCanConvert(TypeobjectType){returnobjectType==typeof(Dictionary);}}publicoverrideobjectReadJson(JsonReaderreader,TypeobjectType,objectexistingValue,JsonSerializerserializer){KeyValuePair[]对;JTokentoken=JToken.Load(阅读器);if(token.Type==JTokenType.Array){pairs=token.ToObject[]>(serializer);}else{JArray数组=newJArray();array.Add(令牌);pairs=token.ToObject[]>(serializer);}if(pairs==null)返回null;返回pairs.ToDictionary(pair=>pair.Key,pair=>pair.Value);}publicoverridevoidWriteJson(JsonWriterwriter,objectvalue,JsonSerializerserializer){if(value==null)return;varpairs=((IDictionary)value).ToArray();serializer.Serialize(writer,pairs);作为替代方案,您可以密封MyValue类并附加适当的TypeConverterAttribute以将&转换为字符串JSON.Net将拾取它并将其用于字典键和属性。此解决方案更简单,因为它是一个全局解决方案,因此您不需要为每个字典使用代理数组或转换器属性,但为MyValue属性创建的JSON并不是您所需要的。从而:publicclassMyValueConverter:TypeConverter{publicoverrideboolCanConvertFrom(ITypeDescriptorContextcontext,TypesourceType){if(sourceType==typeof(string)){returntrue;}returnbase.CanConvertFrom(context,sourceType);}publicoverrideobjectConvertFrom(ITypeDescriptorContextcontext,CultureInfoculture,objectvalue){if(valueisstring){//不能在这里执行JsonConvert.DeserializeObject因为它会导致stackoverflow异常。使用(varreader=newJsonTextReader(newStringReader((string)value))){JObjectitem=JObject.Load(reader);如果(项目==null)返回null;MyValuemyValue=newMyValue();varprop1=item["Prop1"];如果(prop1!=null)myValue.Prop1=prop1.ToString();varprop2=item["Prop2"];如果(prop2!=null)myValue.Prop2=prop2.ToString();返回我的价值;}}returnbase.ConvertFrom(context,culture,value);}publicoverrideobjectConvertTo(ITypeDescriptorContextcontext,CultureInfo文化,对象值,类型destinationType){if(destinationType==typeof(string)){MyValuemyValue=(MyValue)value;//不能在这里做JsonConvert.SerializeObject因为它会导致stackoverflow异常。StringBuildersb=newStringBuilder();使用(StringWritersw=newStringWriter(sb,CultureInfo.InvariantCulture))使用(JsonTextWriterjsonWriter=newJsonTextWriter(sw)){jsonWriter.WriteStartObject();jsonWriter.WritePropertyName("Prop1");jsonWriter.WriteValue(myValue.Prop1);jsonWriter.WritePropertyName("Prop2");jsonWriter.WriteValue(myValue.Prop2);jsonWriter.WriteEndObject();返回sw.ToString();}}returnbase.ConvertTo(context,culture,value,destinationType);}}[TypeConverter(typeof(MyValueConverter))]publicclassMyValue{publicMyValue(){}publicMyValue(stringprop1,stringprop2){this.Prop1=prop1;这个.Prop2=prop2;}publicStringProp1{得到;放;}publicStringProp2{得到;放;}公共覆盖布尔Equals(objectobj){if(ReferenceEquals(this,obj))返回真;elseif(ReferenceEquals(obj,null))返回false;如果(GetType()!=obj.GetType())返回false;varother=(MyValue)obj;返回Prop1==other.Prop1&&Prop2==other.Prop2;}publicoverrideintGetHashCode(){unchecked{uintcode=0;如果(Prop1!=null)代码^=(uint)Prop1。获取哈希码();代码=(代码>16);如果(Prop2!=null)代码^=(uint)Prop2.GetHashCode();返回(整数)代码;}}publicoverridestringToString(){returnTypeDescriptor.GetConverter(GetType()).ConvertToString(this);}publicstaticbooloperator==(MyValuefirst,MyValuesecond){if(ReferenceEquals(first,null))returnReferenceEquals(second,null);返回first.Equals(second);}publicstaticbooloperator!=(MyValuefirst,MyValuesecond){return!(first==second);使用此类的属性和字典现在可以在不使用任何代理数组的情况下进行序列化例如,序列化和反序列化以下内容:publicclassMyContainer{publicMyContainer(){this.Dictionary=newDictionary();}publicMyValueMyValue{得到;放;}publicDictionary字典{get;放;}}Sequence在呈现时提供以下JSON:{"MyValue":"{"Prop1":"AProperty","Prop2":"Atthetoplevel"}","Dictionary":{"{"Prop1":"A","Prop2":"A"}":1,"{"Prop1":"B","Prop2":"B"}":2}}(引号被转义,因为它们嵌入在JSON,不是JSON的一部分。)延迟更新——为字典键创建一个通用类型转换器通过使用适当的契约解析器,可以为任何通用指定类型创建一个通用类型转换器:publicclassNoTypeConverterContractResolver:DefaultContractResolver{readonlyTypetype;publicNoTypeConverterContractResolver(Typetype):base(){if(type==null)thrownewArgumentNullException();if(type==typeof(string)||type.IsPrimitive)thrownewArgumentException("type==typeof(string)||type.IsPrimitive");这个.type=类型;}protectedoverrideJsonContractCreateContract(TypeobjectType){if(type.IsAssignableFrom(objectType)){//替换指定类型的JsonStringContract。varcontract=this.CreateObjectContract(objectType);退货合同;}返回基础.CreateContract(objectType);}}publicclassGenericJsonTypeConverter:TypeConverter{//从7.0.1开始,出于性能原因,Json.NET建议对“无状态”契约解析器使用静态实例。//http://www.newtonsoft.com/json/help/html/ContractResolver.htm//http://www.newtonsoft.com/json/help/html/M_Newtonsoft_Json_Serialization_DefaultContractResolver__ctor_1.htm//“在您的应用程序中使用无参数构造函数和缓存契约解析器实例以获得最佳性能。”静态NoTypeConverterContractResolvercontractResolver;staticNoTypeConverterContractResolverContractResolver{get{if(contractResolver==null)Interlocked.CompareExchange(refcontractResolver,newNoTypeConverterContractResolver(typeof(T)),null);}返回合同解析器;}}publicoverrideboolCanConvertFrom(ITypeDescriptorContextcontext,TypesourceType){if(sourceType==typeof(string)){返回真;}returnbase.CanConvertFrom(context,sourceType);}publicoverrideobjectConvertFrom(ITypeDescriptorContextcontext,CultureInfoculture,objectvalue){if(valueisstring){使用(varreader=newJsonTextReader(newStringReader((string)value))){varobj=JsonSerializer.Create(new杰森斯}}publicoverrideobjectConvertTo(ITypeDescriptorContextcontext,CultureInfoculture,objectvalue,TypedestinationType){(destinationType==typeof(string)){StringBuildersb=newStringBuilder();使用(StringWritersw=newStringWriter(sb,CultureInfo.InvariantCulture))}返回sb.ToString();}returnbase.ConvertTo(context,culture,value,destinationType);然后像下面这样把它应用到你的类中如图:以上是C#学习教程:UsingJSON.Net使用JSON.Net在字典中使用JSON.Net。—[TypeConverter(typeof(GenericJsonTypeConverter))]publicclassMyValue{}收藏,不代表立场,如涉及侵权,请点击维权联系管理员删除如转载请注明出处: