如何在WCF+HTTP环境中将Dictionary序列化为指定JSON格式
一、Dictionary<string, string> 序列化优化方案
1. 配置DataContractJsonSerializer启用简单字典格式
WCF默认的DataContractJsonSerializer会把Dictionary序列化成包含Key/Value的数组,开启UseSimpleDictionaryFormat即可让它直接序列化为键值对结构。有两种配置方式:
方式一:Web.config配置
修改项目的Web.config,在system.serviceModel节点下添加行为配置,并绑定到服务端点:
<system.serviceModel> <behaviors> <endpointBehaviors> <behavior name="WebHttpBehavior"> <webHttp> <!-- 启用简单字典格式,同时可配置日期格式 --> <jsonSerialization useSimpleDictionaryFormat="true" dateTimeFormat="yyyy-MM-ddTHH:mm:ss" /> </webHttp> </behavior> </endpointBehaviors> </behaviors> <services> <service name="YourServiceNamespace.YourService"> <endpoint address="" behaviorConfiguration="WebHttpBehavior" binding="webHttpBinding" contract="YourServiceNamespace.IYourService" /> </service> </services> </system.serviceModel>
方式二:代码自定义行为配置
如果需要更灵活的代码控制,可以创建自定义WebHttpBehavior,重写格式化器创建逻辑:
public class CustomWebHttpBehavior : WebHttpBehavior { protected override IDispatchMessageFormatter CreateReplyDispatchFormatter(OperationDescription operationDescription, ServiceEndpoint endpoint) { var settings = new DataContractJsonSerializerSettings { UseSimpleDictionaryFormat = true, // 同时配置日期序列化格式 DateTimeFormat = new DateTimeFormat("yyyy-MM-ddTHH:mm:ss") }; return new DataContractJsonSerializerOperationFormatter(operationDescription, endpoint, settings); } }
然后在服务启动时(比如Global.asax的Application_Start方法)注册该行为:
protected void Application_Start(object sender, EventArgs e) { // 路由方式注册服务时绑定行为 var route = new ServiceRoute("YourService", new WebServiceHostFactory(), typeof(YourService)); RouteTable.Routes.Add(route); // 或者直接使用ServiceHost时添加行为 var host = new ServiceHost(typeof(YourService)); var endpoint = host.AddServiceEndpoint(typeof(IYourService), new WebHttpBinding(), ""); endpoint.Behaviors.Add(new CustomWebHttpBehavior()); host.Open(); }
2. 使用[JsonExtensionData]属性
如果你的Dictionary是某个DataContract类的属性,可以给该属性标记[JsonExtensionData],序列化时会自动将字典的键值对展开为JSON对象的顶级属性:
[DataContract] public class ServiceResponse { // 其他DataMember属性... [JsonExtensionData] public Dictionary<string, string> ExtraProperties { get; set; } }
返回ServiceResponse对象时,ExtraProperties里的键值对会直接变成JSON的同级属性,符合预期格式。
3. 关于[JsonDictionary]属性的说明
[JsonDictionary]是Newtonsoft.Json(Json.NET)中的属性,仅当你将WCF默认的序列化器替换为Json.NET时才生效。WCF默认使用DataContractJsonSerializer,所以这个属性在当前场景下不适用。
二、日期反序列化问题解决方案
日期格式问题同样可以通过DataContractJsonSerializerSettings统一配置:
- 在代码配置中,给
DataContractJsonSerializerSettings设置DateTimeFormat指定格式 - 在Web.config的
<jsonSerialization>节点中通过dateTimeFormat属性指定格式
如果需要更灵活的日期处理,也可以替换WCF的序列化器为Json.NET(参考上文自定义JsonNetFormatter的方案),利用Json.NET强大的日期格式化能力,比如设置DateFormatString或者自定义日期转换器。
内容的提问来源于stack exchange,提问作者Nate Anderson

