gpt4 book ai didi

asp.net-web-api - Json.Net TypeNameHandling.Auto 和 Asp Web Api Controller 给出了意外行为

转载 作者:行者123 更新时间:2023-12-04 04:33:22 26 4
gpt4 key购买 nike

假设 TypeNameHandling.Auto用于以下 Web Api Controller 中的 Json.net:

class A {}
class B : A {}

class FooController : ApiController
{
public A Get() {
return new A();
}
}

class BarController : ApiController
{
public A Get() {
return new B();
}
}

然后我希望生成的 Json 是:


{}

酒吧
{'$type':...}

但是,Bar 的输出也是 {} .另一方面,如果 API Controller 返回 IEnumerable<A>我们退回了很多 B 's 然后类型属性被设置。

是否可以更改此行为,使其使用返回类型作为 Json.Net 的输入?

解决方法是返回 Json 而不是对象,但我发现这是一个不满意的解决方案。

最佳答案

感谢这种情况,因为我认为这应该默认包含在我们的 Json 格式化程序中。以下是一个自定义的 Json 格式化程序,我尝试将“类型”信息传递给 Serialize JsonSerializer的方法.我在您的场景中尝试了以下自定义格式化程序,它似乎工作正常。

(下面的大部分代码都是从现有的 Web API 源代码中精心挑选的,以适合您的场景。)

public class CustomJsonFormatter : JsonMediaTypeFormatter
{
public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext)
{
try
{
Encoding effectiveEncoding = SelectCharacterEncoding(content == null ? null : content.Headers);

if (!UseDataContractJsonSerializer)
{
using (JsonTextWriter jsonTextWriter = new JsonTextWriter(new StreamWriter(writeStream, effectiveEncoding)) { CloseOutput = false })
{
if (Indent)
{
jsonTextWriter.Formatting = Newtonsoft.Json.Formatting.Indented;
}

JsonSerializer jsonSerializer = JsonSerializer.Create(this.SerializerSettings);
jsonSerializer.Serialize(jsonTextWriter, value, type); //NOTE: passing in 'type' here
jsonTextWriter.Flush();
}
}
else
{
return base.WriteToStreamAsync(type, value, writeStream, content, transportContext);
}

return TaskHelpers.Completed();
}
catch (Exception e)
{
return TaskHelpers.FromError(e);
}
}
}

internal class TaskHelpers
{
private static readonly Task _defaultCompleted = FromResult<AsyncVoid>(default(AsyncVoid));

/// <summary>
/// Used as the T in a "conversion" of a Task into a Task{T}
/// </summary>
private struct AsyncVoid
{
}

internal static Task<TResult> FromResult<TResult>(TResult result)
{
TaskCompletionSource<TResult> tcs = new TaskCompletionSource<TResult>();
tcs.SetResult(result);
return tcs.Task;
}

/// <summary>
/// Returns an error task. The task is Completed, IsCanceled = False, IsFaulted = True
/// </summary>
internal static Task FromError(Exception exception)
{
return FromError<AsyncVoid>(exception);
}

/// <summary>
/// Returns an error task of the given type. The task is Completed, IsCanceled = False, IsFaulted = True
/// </summary>
/// <typeparam name="TResult"></typeparam>
internal static Task<TResult> FromError<TResult>(Exception exception)
{
TaskCompletionSource<TResult> tcs = new TaskCompletionSource<TResult>();
tcs.SetException(exception);
return tcs.Task;
}

/// <summary>
/// Returns a completed task that has no result.
/// </summary>
internal static Task Completed()
{
return _defaultCompleted;
}
}

关于asp.net-web-api - Json.Net TypeNameHandling.Auto 和 Asp Web Api Controller 给出了意外行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20167895/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com