PHP*_*oob 0 .net c# asp.net .net-core asp.net-core
我有一个 asp.net core 方法,我希望它接受 RAW json,我不知道也不会总是知道 json 对象的架构,所以我使用dynamic types
点表示法。
当我将 json 转义为每个字符时,此方法有效。我尝试过直接使用 json body,但这不起作用。所以看来我的选择是Serialize
然后Deserialize
是 json. (非常多余)但如果我尝试直接使用 JSON 主体,它似乎会以任何其他方式抛出错误。
在调试器中,一切似乎都适用于对象/字符串的序列化和反序列化,但当我尝试将对象转换为字符串并给出错误时,会在 id(属性)上引发错误。(尽管在调试器中我能够正确地看到 ID)。
({Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: Cannot convert type 'System.Text.Json.JsonElement' to 'string')}
我真的不明白为什么它给出了字符串类型但无法转换它。我什至尝试删除铸造,但仍然收到此错误。
public IActionResult Post([FromBody] ExpandoObject requestInput)
{
try
{
//Makes a JSON String
var stringObject = (string) JsonSerializer.Serialize(requestInput);
DateTime time = DateTime.UtcNow;
// Recreated the Json Object
dynamic requestObject = JsonSerializer.Deserialize<ExpandoObject>(stringObject);
// Throws Error here, yet it shows Value as the correct Id number (Value: Type String)
string reqObject = (string) requestObject.Id;
Run Code Online (Sandbox Code Playgroud)
ExpandoObject
因此.NET Core尚不支持。MS 表示也许会在 .NET 5.0 中添加它。在那之前,您可以使用JsonConverter
我在线程中找到的这个。我将在这里发布代码,以防线程消失。
你可以这样使用它:
[HttpPost, Route("testPost")]
public IActionResult TestPost([FromBody] object obj) // just use "object"
{
// object is: { "hello":"world" }
var myDynamic = JsonSerializer.Deserialize<dynamic>(
JsonSerializer.Serialize(obj), new JsonSerializerOptions
{
Converters = { new DynamicJsonConverter() }
});
var test = (string)myDynamic.hello;
// test will equal "world"
return Ok();
}
Run Code Online (Sandbox Code Playgroud)
这是转换器:
/// <summary>
/// Temp Dynamic Converter
/// by:tchivs@live.cn
/// </summary>
public class DynamicJsonConverter : JsonConverter<dynamic>
{
public override dynamic Read(ref Utf8JsonReader reader,
Type typeToConvert,
JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.True)
{
return true;
}
if (reader.TokenType == JsonTokenType.False)
{
return false;
}
if (reader.TokenType == JsonTokenType.Number)
{
if (reader.TryGetInt64(out long l))
{
return l;
}
return reader.GetDouble();
}
if (reader.TokenType == JsonTokenType.String)
{
if (reader.TryGetDateTime(out DateTime datetime))
{
return datetime;
}
return reader.GetString();
}
if (reader.TokenType == JsonTokenType.StartObject)
{
using JsonDocument documentV = JsonDocument.ParseValue(ref reader);
return ReadObject(documentV.RootElement);
}
// Use JsonElement as fallback.
// Newtonsoft uses JArray or JObject.
JsonDocument document = JsonDocument.ParseValue(ref reader);
return document.RootElement.Clone();
}
private object ReadObject(JsonElement jsonElement)
{
IDictionary<string, object> expandoObject = new ExpandoObject();
foreach (var obj in jsonElement.EnumerateObject())
{
var k = obj.Name;
var value = ReadValue(obj.Value);
expandoObject[k] = value;
}
return expandoObject;
}
private object? ReadValue(JsonElement jsonElement)
{
object? result = null;
switch (jsonElement.ValueKind)
{
case JsonValueKind.Object:
result = ReadObject(jsonElement);
break;
case JsonValueKind.Array:
result = ReadList(jsonElement);
break;
case JsonValueKind.String:
//TODO: Missing Datetime&Bytes Convert
result = jsonElement.GetString();
break;
case JsonValueKind.Number:
//TODO: more num type
result = 0;
if (jsonElement.TryGetInt64(out long l))
{
result = l;
}
break;
case JsonValueKind.True:
result = true;
break;
case JsonValueKind.False:
result = false;
break;
case JsonValueKind.Undefined:
case JsonValueKind.Null:
result = null;
break;
default:
throw new ArgumentOutOfRangeException();
}
return result;
}
private object? ReadList(JsonElement jsonElement)
{
IList<object?> list = new List<object?>();
foreach (var item in jsonElement.EnumerateArray())
{
list.Add(ReadValue(item));
}
return list.Count == 0 ? null : list;
}
public override void Write(Utf8JsonWriter writer,
object value,
JsonSerializerOptions options)
{
// writer.WriteStringValue(value.ToString());
}
}
Run Code Online (Sandbox Code Playgroud)
正如Aluan在评论中dynamic
指出的那样,这是一种更灵活的方法来处理使用上面的转换器。在您的班级中添加以下内容:Startup.cs
services.AddControllers().AddJsonOptions(options =>
options.JsonSerializerOptions.Converters.Add(new DynamicJsonConverter()));
Run Code Online (Sandbox Code Playgroud)
那么你就不必在控制器中做任何愚蠢的事情了。您只需将 body 参数设置为动态即可,它会神奇地起作用:
[HttpPost, Route("testPost")]
public IActionResult TestPost([FromBody] dynamic obj)
{
// object is: { "hello":"world" }
var test = (string)obj.hello;
// test will equal "world"
return Ok();
}
Run Code Online (Sandbox Code Playgroud)
好多了!
归档时间: |
|
查看次数: |
2389 次 |
最近记录: |