如何用.NET Framework的WCF将自定义类序列化为JSON原始类型?
解决方案
方案一:用IDataContractSurrogate扩展DataContractJsonSerializer
这是适配你现有WCF序列化场景的最优方案,无需修改原有类结构,一次定义即可全局复用转换逻辑,彻底解决多处使用时的冗余问题。
1. 实现自定义代理类
创建一个实现IDataContractSurrogate的类,接管目标类型的序列化/反序列化转换逻辑:
public class CustomTypeSurrogate : IDataContractSurrogate { // 指定序列化时自定义类型对应的原始替换类型 public Type GetDataContractType(Type type) { if (type == typeof(Joiner)) return typeof(string); if (type == typeof(SingleIntClass)) return typeof(int); return type; } // 序列化阶段:将自定义对象转换为原始类型值 public object GetObjectToSerialize(object obj, Type targetType) { if (obj is Joiner joiner) return joiner.ToString(); // 复用类已定义的标准字符串表示 if (obj is SingleIntClass intObj) return intObj.IntValue; // 直接返回整数成员的值 return obj; } // 反序列化阶段:将原始类型值转换回自定义对象 public object GetDeserializedObject(object obj, Type targetType) { if (targetType == typeof(Joiner) && obj is string str) return Joiner.Parse(str); // 假设Joiner类有静态Parse方法用于重建对象 if (targetType == typeof(SingleIntClass) && obj is int num) return new SingleIntClass { IntValue = num }; return obj; } // 以下接口方法无需自定义逻辑,返回默认值即可 public object GetCustomDataToExport(Type clrType, Type dataContractType) => null; public object GetCustomDataToExport(MemberInfo memberInfo, Type dataContractType) => null; public void GetKnownCustomDataTypes(Collection<Type> customDataTypes) { } public Type GetReferencedTypeOnImport(string typeName, string typeNamespace, object customData) => null; public CodeTypeDeclaration ProcessImportedType(CodeTypeDeclaration typeDeclaration, CodeCompileUnit compileUnit) => typeDeclaration; }
2. 配置序列化器使用代理
初始化DataContractJsonSerializer时传入代理实例,后续所有序列化/反序列化操作都会自动应用转换规则:
var serializerSettings = new DataContractJsonSerializerSettings { DataContractSurrogate = new CustomTypeSurrogate(), UseSimpleDictionaryFormat = true }; // 序列化示例:Joiner数组会被转换为字符串数组 var joinerList = new List<Joiner> { new Joiner { A = "foo", B = "bar" }, new Joiner { A = "hello", B = "world" } }; using (var stream = new MemoryStream()) { var serializer = new DataContractJsonSerializer(typeof(List<Joiner>), serializerSettings); serializer.WriteObject(stream, joinerList); stream.Position = 0; var jsonResult = new StreamReader(stream).ReadToEnd(); // 输出结果类似 ["foo,bar", "hello,world"],而非嵌套对象数组 } // 反序列化示例 using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(jsonResult))) { var serializer = new DataContractJsonSerializer(typeof(List<Joiner>), serializerSettings); var deserializedList = (List<Joiner>)serializer.ReadObject(stream); }
方案二:用.NET Framework 4.8自带的System.Text.Json
如果你的环境允许使用System.Text.Json(.NET Framework 4.8可通过NuGet安装,部分Windows 10版本也自带),可以通过自定义转换器实现更简洁的逻辑:
1. 编写类型转换器
public class JoinerConverter : JsonConverter<Joiner> { public override Joiner Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { return Joiner.Parse(reader.GetString()); } public override void Write(Utf8JsonWriter writer, Joiner value, JsonSerializerOptions options) { writer.WriteStringValue(value.ToString()); } } public class SingleIntClassConverter : JsonConverter<SingleIntClass> { public override SingleIntClass Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { return new SingleIntClass { IntValue = reader.GetInt32() }; } public override void Write(Utf8JsonWriter writer, SingleIntClass value, JsonSerializerOptions options) { writer.WriteNumberValue(value.IntValue); } }
2. 配置并使用序列化器
var jsonOptions = new JsonSerializerOptions(); jsonOptions.Converters.Add(new JoinerConverter()); jsonOptions.Converters.Add(new SingleIntClassConverter()); // 序列化 var json = JsonSerializer.Serialize(joinerList, jsonOptions); // 反序列化 var deserialized = JsonSerializer.Deserialize<List<Joiner>>(json, jsonOptions);
关键注意点
- 确保
Joiner类有可靠的ToString()(序列化用)和静态Parse()(反序列化用)方法;SingleIntClass要保证整数成员的访问权限正常。 - 方案一完全基于WCF自带类,无额外依赖,适合环境受限的场景;方案二更简洁,但需确认环境支持
System.Text.Json。
内容的提问来源于stack exchange,提问作者bchase
相关产品推荐
相关产品推荐

