- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
所以我有一个 ApiController...
public class MetaDataController : ApiController
{
[HttpPost]
public HttpResponseMessage Test(TestModel model)
{
//Do Stuff
return new HttpResponseMessage(HttpStatusCode.OK);
}
}
接受模型...
[JsonObject(ItemRequired = Required.Always)]
public class TestModel
{
public int Id { get; set; }
public IEnumerable<SubModel> List { get; set; }
}
public class SubModel
{
public int Id { get; set; }
}
以Json的形式...
{ "Id": 1, "List": [{ "Id": 11 }, { "Id": 12 } ] }
当发布到此 Controller 操作时,TestModel 上的属性应该使 Json.Net 在 Json 缺少属性时抛出 JsonSerializationException。我围绕确保此行为按预期工作编写了单元测试。
[Test]
public void Test()
{
var goodJson = @"{ 'Id': 1,
'List': [ {'Id': 11}, {'Id': 12} ]
}";
Assert.DoesNotThrow(() => JsonConvert.DeserializeObject<TestModel>(goodJson));
var badJson = @"{ 'Id': 1 }";
Assert.That(()=>JsonConvert.DeserializeObject<TestModel>(badJson),
Throws.InstanceOf<JsonSerializationException>().
And.Message.Contains("Required property 'List' not found in JSON."));
}
将格式良好的 Json 发布到 controlr 操作时,一切正常。但是,如果该 json 缺少必需的属性,则不会抛出异常。映射到缺失属性的 TestModel 成员为空。
为什么 JsonConvert 按预期工作,但通过 WebApiController 自动 Json 反序列化无法遵守 TestModel 上的属性?
最佳答案
对于咯咯笑声,我决定额外确保我的应用程序使用 Json.Net 进行 json 反序列化。所以我写了一个 MediaTypeFormatter
public class JsonTextFormatter : MediaTypeFormatter
{
public readonly JsonSerializerSettings JsonSerializerSettings;
private readonly UTF8Encoding _encoding;
public JsonTextFormatter(JsonSerializerSettings jsonSerializerSettings = null)
{
JsonSerializerSettings = jsonSerializerSettings ?? new JsonSerializerSettings();
SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json"));
_encoding = new UTF8Encoding(false, true);
SupportedEncodings.Add(_encoding);
}
public override bool CanReadType(Type type)
{
if (type == null)
{
throw new ArgumentNullException();
}
return true;
}
public override bool CanWriteType(Type type)
{
return true;
}
public override Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
{
var serializer = JsonSerializer.Create(JsonSerializerSettings);
return Task.Factory.StartNew(() =>
{
using (var streamReader = new StreamReader(readStream, _encoding))
{
using (var jsonTextReader = new JsonTextReader(streamReader))
{
return serializer.Deserialize(jsonTextReader, type);
}
}
});
}
public override Task WriteToStreamAsync(Type type, Object value, Stream writeStream, HttpContent content, TransportContext transportContext)
{
var serializer = JsonSerializer.Create(JsonSerializerSettings);
return Task.Factory.StartNew(() =>
{
using (
var jsonTextWriter = new JsonTextWriter(new StreamWriter(writeStream, _encoding))
{
CloseOutput = false
})
{
serializer.Serialize(jsonTextWriter, value);
jsonTextWriter.Flush();
}
});
}
}
并修改了我的 WebApiConfig 以使用它而不是默认值。
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Filters.Add(new HandleSerializationErrorAttribute());
config.Formatters.RemoveAt(0);
var serializerSettings = new JsonSerializerSettings
{
MissingMemberHandling = MissingMemberHandling.Error
};
config.Formatters.Insert(0, new JsonTextFormatter(serializerSettings));
}
}
我还添加了一个 ExceptionFilterAttribute 来捕获序列化错误并返回有关错误的相关信息。
public class HandleSerializationErrorAttribute : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext context)
{
if (context.Exception is JsonSerializationException)
{
var responseMessage = new HttpResponseMessage(HttpStatusCode.BadRequest);
responseMessage.Content = new StringContent(JsonConvert.SerializeObject(context.Exception.Message));
context.Response = responseMessage;
}
}
}
所以它是:.net MVC 4 WebApi 说它使用 Json.Net,但默认的 JsonFormatter 拒绝遵守装饰我的模型的 Json 属性。手动明确设置格式化程序可解决此问题。
关于c# - WebApi 无法遵守 JsonObjectAttribute 设置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25026336/
JSON.NET JsonObjectAttribute有属性(property)Id 。它继承自 JsonContainerAttribute 。我找不到,Id 属性的用途是什么? 最佳答案 由 J
所以我有一个 ApiController... public class MetaDataController : ApiController { [HttpPost] public
我是一名优秀的程序员,十分优秀!