自定义用于调用Action的ASP Web API Json序列化



我正在考虑将一个现有的JSON api从一个糟糕的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
        }));
    }
}

在WebApi中,我看到我可以从配置中获得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并以某种方式在那里工作吗?我还有什么其他选择?

我从未见过有人想用这种方式控制序列化。但为了用最少的返工量实现您的目标,我会直接从您的方法返回所有信息:

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
}

相关内容

  • 没有找到相关文章

最新更新