【问题标题】:Where should I plug in my custom DefaultContractResolver JSON.NET?我应该在哪里插入我的自定义 DefaultContractResolver JSON.NET?
【发布时间】:2014-07-03 00:56:37
【问题描述】:

我在 ASP.Net 中有一个 WebAPI 2.0 项目,在该项目中我实现了一个自定义 DefaultContractResolver,以便我可以控制如何使用 JSON.Net 将我的实体序列化为 JSON;但是我不确定如何告诉框架使用我的自定义实现。我还想知道是否可以更改特定控制器/操作的 ContractResolver。

谢谢!

--- 编辑 03/07/2014 我已经通过创建一个新的 ConfigSettings 对象并手动解析该对象来弄清楚如何使用我的自定义实现;然而,生成的 JSON 被序列化了两次(它有额外的 \r\n 字符)。这是因为 webAPI 控制器默认序列化响应,所以我想更改以覆盖该行为...这是正确的方法吗?

【问题讨论】:

  • 斯科特·艾伦的this short post 有帮助吗?
  • 很棒的帖子,虽然我想避免更改 JsonConverter 的全局设置。这个link[link] 看起来也不错,我正在测试它。

标签: c# asp.net json asp.net-web-api2


【解决方案1】:

我刚刚经历了自己弄清楚这一点的痛苦,我需要一个可以根据请求工作的。您可以使用该方法并返回相同的媒体格式化程序。我发现在GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ContractResolver 上设置格式化程序对于每个请求的需求有点不可靠,即使我尝试在该类的一个实例中处理每个请求的需求。但是,您可以尝试在 App_Start 代码中的某处设置您的 ContractResolver 实例

我最终创建了一个自定义 JsonMediaTypeFormatter,用于检查是否为请求配置了 ContractResolver,您可以只返回一个相同的解析器:

public class DynamicJsonMediaTypeFormatter : JsonMediaTypeFormatter
{ 
public override MediaTypeFormatter GetPerRequestFormatterInstance(Type type, System.Net.Http.HttpRequestMessage request, System.Net.Http.Headers.MediaTypeHeaderValue mediaType)
{
// shown is getting the current formatter, but you can return an instance you prefer
  var formatter = base.GetPerRequestFormatterInstance(type, request, mediaType) as JsonMediaTypeFormatter; 

// Here I had more code to get the resolver based on request, skipped
  ((JsonMediaTypeFormatter)formatter).SerializerSettings.ContractResolver = <YourContractResolverInstance>;
    return formatter;
}
}

我想你已经弄清楚了那个部分,但是你的合约解析器可以覆盖“CreateProperties”,并让你自己的逻辑决定将出现哪些 json 属性以及它们将使用哪些名称(为了完整性和其他读者的利益而添加) :

public class DynamicContractResolver : DefaultContractResolver
{
...
 protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization){
  ...
}

【讨论】:

  • 这正是我决定创建自己的实现以覆盖 CreateProperties 方法的原因。
【解决方案2】:

我最终改变了我的方法的返回类型,如下所示:

假设我们有这个简单的 Foo 类:

public class Foo
{
    public string Bar {get; set;}
}

使用 ASP WebApi 2.0,GET 的脚手架控制器方法将如下所示:

// GET api/Foo
public IQueryable<Foo> GetFoos()
{
    var foos = GetAListOfFoosFromSomewhere() //returns an IQueryable<Foo>
    return Foos
}

请注意,框架会自动将 Foos 序列化为 JSON。

所以我所做的就是将方法更改为:

// GET api/Foo
public HttpResponseMessage GetFoos()
{
    var foos = GetAListOfFoosFromSomewhere(); //returns an IQueryable<Foo>
    var settings = new JsonSerializerSettings()
    {
     ContractResolver= new MyCustomContractResolver(), //Put  your custom implementation here
     //Also set up ReferenceLoopHandling as appropiate
    };
    var jsoncontent = JsonConvert.SerializeObject(foos, settings);
    var response = new HttpResponseMessage(HttpStatusCode.OK)
    {
        Content = new StringContent(jsoncontent, Encoding.UTF8, "application/json")
    };
    return response;
}

在我的解决方案中,我添加了一个方便的方法来创建 HttpResponseMessage,所以它看起来有点像这样:

public HttpResponseMessage GetFoos()
{
    var foos = GetAListOfFoosFromSomewhere() //returns an IQueryable<Foo>
    return CreateResponse(foos);
}

mercury2269 的这篇文章真的很有帮助。

【讨论】:

  • 这种方法的一个问题是,如果您大量使用自定义合约解析器,您最终会在整个项目中复制大量代码
  • 不是真的,这就是我添加便捷方法的原因。
猜你喜欢
  • 2020-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多