我正在考虑将现有的JSON api从hacky MVC3实现转换为最新的MVC4 Web Api。 MVC3实现使用JSON.NET来完成所有序列化,这将使升级变得美观和流畅。
我无法定制某些操作的结果如何被序列化。例如,我想要一些动作只返回输出对象的一些属性,而其他动作可能会进行深度序列化。在我当前的实现中,操作可以通过在HttpContext
中设置适当的设置来添加一系列序列化覆盖。这些后来通过从JsonResult
派生的类来获取自定义序列化。添加自定义JsonConverters
的主要用途是控制和减少序列化的键/值的数量,并根据操作改变要序列化的参数(某些操作应返回比其他操作更多的对象参数)。
在我当前的MVC3实现中控制器和控制json序列化的类的简明示例:
public class TestController : JsonController {
public JsonResult Persons() {
ControllerContext.HttpContext.Items[typeof(IEnumerable<JsonConverter>)] = new JsonConverter[] {
new InterfaceExtractorJsonConverter<IPersonForList>(),
new StringEnumConverter()
};
ControllerContext.HttpContext.Items[typeof(IContractResolver)] = new SpecialCamelCasePropertyNamesContractResolver();
}
}
public class JsonNetResult : JsonResult {
public override void ExecuteResult(ControllerContext context) {
var response = context.HttpContext.Response;
var additionalConverters = context.HttpContext.Items[typeof(IEnumerable<JsonConverter>)] as IEnumerable<JsonConverter> ?? Enumerable.Empty<JsonConverter>();
var contractResolver = context.HttpContext.Items[typeof(IContractResolver)] as IContractResolver ?? new JsonContractResolver();
var typeNameHandling = TypeNameHandling.None;
if (context.HttpContext.Items.Contains(typeof(TypeNameHandling)))
typeNameHandling = (TypeNameHandling)context.HttpContext.Items[typeof(TypeNameHandling)];
response.Write(JsonConvert.SerializeObject(Data, Formatting.Indented, new JsonSerializerSettings {
ContractResolver = contractResolver,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
Converters = additionalConverters,
TypeNameHandling = typeNameHandling
}));
}
}
在Web Api中,我看到我可以从配置中获取Json格式化程序并全局更改序列化。
var config = new HttpSelfHostConfiguration("http://localhost:8080");
var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().Single();
jsonFormatter.SerializerSettings.ContractResolver = new SpecialCamelCasePropertyNamesContractResolver();
jsonFormatter.SerializerSettings.Converters = new[] { new InterfaceExtractorJsonConverter<ITesting>() };
但是,我计划通过添加一些属性来指定要使用的JsonConverter's
来单独控制行动的序列化(或每个控制器)。因此,我希望Json序列化程序找到赋予调用的操作/控制器的相关属性并相应地更改序列化。我不知道在哪里以及如何做到这一点。我应该继承JsonMediaTypeFormatter
并以某种方式在那里工作吗?我还有其他选择吗?
答案 0 :(得分:2)
我从未见过有人想以这种方式控制序列化。但是为了通过最少量的返工来实现您的目标,我将直接从您的方法返回所有这些信息:
class JsonNetResponse {
public IContractResolver ContractResolver { get;set; }
// Other Json.Net bits
public object Value { get; set; }
}
然后我会创建一个自定义格式化程序,而不是处理这些对象:
class JsonNetFormatter : MediaTypeFormatter {
public override bool CanWriteType(Type t) {
return typeof(JsonNetResponse).IsAssignableFrom(t);
}
// TODO WriteToStreamAsync which is basically a copy of your original JsonNetResult
}