我知道ASP.NET Web API本身使用Json.NET来(反)序列化对象,但有没有办法指定JsonSerializerSettings你想要它使用的对象?
例如,如果我想将type信息包含在序列化的JSON字符串中该怎么办?通常我会在.Serialize()调用中注入设置,但Web API会默默地执行此操作.我找不到手动注入设置的方法.
我有一个Web API项目,它返回一些产品数据.它根据请求的Accept标头(JSON/XML)正确协商返回类型.问题是,如果没有指定Accept标头,则返回XML,但我希望它默认返回JSON
http://website.com/MyPage?type=json // returns json
http://website.com/MyPage?type=xml // returns xml
http://website.com/MyPage // returns xml by default
Run Code Online (Sandbox Code Playgroud)
这是我目前的代码如下:
GlobalConfiguration.Configuration.Formatters.XmlFormatter.MediaTypeMappings.Add(
new QueryStringMapping("type", "xml", new MediaTypeHeaderValue("application/xml")));
GlobalConfiguration.Configuration.Formatters.JsonFormatter.MediaTypeMappings.Add(
new QueryStringMapping("type", "json", new MediaTypeHeaderValue("application/json")));
Run Code Online (Sandbox Code Playgroud) 我们有一个最近被移动到新服务器的WEB API项目.在对其有效负载进行一些添加之后,我正在运行我的项目,但它突然抛出以下错误:
无法将"System.Net.Http.Formatting.JsonContractResolver"类型的对象强制转换为"Newtonsoft.Json.Serialization.DefaultContractResolver".
有问题的代码行在global.asax中:
protected void Application_Start() {
GlobalConfiguration.Configure(WebApiConfig.Register);
var serializerSettings =
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings;
var contractResolver =
(DefaultContractResolver)serializerSettings.ContractResolver;
contractResolver.IgnoreSerializableAttribute = true;
}
Run Code Online (Sandbox Code Playgroud)
我相信这段代码是因为API的默认输出是XML而添加的,我们需要它来代替JSON.
突出显示(DefaultContractResolver)会显示一个工具提示,指示它的引用NewtonSoft.JSon.Serialization.DefaultContractResolver.突出显示serializersettings.ContractResolver引用IContractResolver JSonSerializerSettings.ContractResolver.
代码已经在这台机器上存在了一段时间,我认为我唯一能改变的是安装更新版本的.NET.
什么可能导致这行代码突然抛出错误?我该如何解决?
谢谢!
编辑:根据评论中的请求,我的序列化代码包含如下内容:
json += "{\"employeename\": \"" + Convert.ToString(reader["Employee"])
+ "\"},";
return JsonConvert.DeserializeObject<OrgChartModel>(json);
Run Code Online (Sandbox Code Playgroud)
Edit2:我们现在正在运行.NET 4.5.据我所知,我们之前跑过4.2,但看到它已经过了几个月,我无法确定.
根据Dominick的评论,我尝试将强制转换为DefaultContractResolver更改为:
var contractResolver =
(IContractResolver)serializerSettings.ContractResolver;
Run Code Online (Sandbox Code Playgroud)
但是,这会在API中返回以下错误:
{"Message":"The requested resource does not support http method 'GET'."}
我正在尝试从WebApi v2(完整框架,而不是点网核心)中的snake_cased JSON绑定我的PascalCased c#模型。
这是我的API:
public class MyApi : ApiController
{
[HttpPost]
public IHttpActionResult DoSomething([FromBody]InputObjectDTO inputObject)
{
database.InsertData(inputObject.FullName, inputObject.TotalPrice)
return Ok();
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的输入对象:
public class InputObjectDTO
{
public string FullName { get; set; }
public int TotalPrice { get; set; }
...
}
Run Code Online (Sandbox Code Playgroud)
我的问题是JSON看起来像这样:
{
"full_name": "John Smith",
"total_price": "20.00"
}
Run Code Online (Sandbox Code Playgroud)
我知道我可以使用JsonProperty属性:
public class InputObjectDTO
{
[JsonProperty(PropertyName = "full_name")]
public string FullName { get; set; }
[JsonProperty(PropertyName = "total_price")]
public int TotalPrice { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
但是我的InputObjectDTO 很大 …
我使用TypeNameHandling在json中序列化和反序列化派生类的列表.它与属性和属性完美配合JsonProperty
public abstract class Animal
{
public bool CanFly { get; set;}
}
public class FlyingAnimal : Animal
{
public FlyingAnimal() { this.CanFly = true; }
}
public class SwimmingAnimal : Animal
{
public SwimmingAnimal() { this.CanFly = false; }
}
public class World
{
public World() {
this.Animals = new List<Animal>();
this.Animals.Add(new FlyingAnimal());
this.Animals.Add(new SwimmingAnimal());
}
[JsonProperty(ItemTypeNameHandling = TypeNameHandling.Auto)]
public List<Animal> Animals { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
现在,我需要一个返回派生类列表的WebAPI:
[RoutePrefix("Animals")]
public class AnimalsController : ApiController
{
public …Run Code Online (Sandbox Code Playgroud) 我正在为Stack Exchange API创建类.所述filter_object类型包含一个成员filter_type,其将或者safe,unsafe或invalid.所以我创建了一个这样的枚举:
[JsonConverter(typeof(StringEnumConverter))]
public enum FilterType
{
safe,
@unsafe, // Here lies the problem.
invalid
}
Run Code Online (Sandbox Code Playgroud)
既然unsafe是关键字,我必须为它添加一些前缀.但是如何使值"不安全"自动映射到@unsafe?示例JSON:
{
"filter": "....",
"filter_type": "unsafe",
"included_fields": [
"...",
"....",
"....."
]
}
Run Code Online (Sandbox Code Playgroud)
如何反序列化它,以便filter_type自动转换为FilterType.@unsafe?
更新 - 解决:
在标识符之前使用@符号可以使其与关键字相同.即使@出现在intellisense中,它也能正常工作.
我正在创建一个带有子项(嵌套对象)的复杂对象,以便从我的web api控制器返回.该对象包含其他对象类型的列表.列表中的这些子对象类型遵循.NET中使用的pascal大小写.
var persons = peopleLookup.Values;
var users = userLookup.Values;
var roles = rolesLookup.Values;
var groups = groupLookup.Values;
var roleAssignments = roleAssignmentLookup.Values;
var groupMembers = groupMemberLookup.Values;
return new { persons, users, roles, roleAssignments, groups, groupMembers };
Run Code Online (Sandbox Code Playgroud)
我的问题是WebAPI没有驼峰的情况下子项的每个属性.例如,人员列表中的第一个人应该具有id,name的属性,而不是Id,Name的.NET pascal案例.同样适用于所有其他子项目.