[英]Accepting raw JSON Asp.net core
我有一個 asp.net 核心方法,我希望它接受 RAW json,我不知道也不會總是知道 json 對象的模式,所以我使用帶點符號的dynamic types
。
當我將 json 字符串轉義為每個字符時,此方法有效。 我曾嘗試直接使用 json 主體,但這不起作用。 所以看起來我的選擇是Serialize
然后Deserialize
json。 (非常多余)但如果我嘗試直接使用 JSON 主體,它似乎會以任何其他方式拋出錯誤。
在調試器中,一切似乎都適用於對象/字符串的序列化和反序列化,但是當我嘗試將對象轉換為字符串並給出錯誤時,會在 id(property) 上引發錯誤。 (雖然在調試器中我能夠正確地看到 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;
因此,.NET Core 中尚不支持ExpandoObject
。 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();
}
這是轉換器:
/// <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());
}
}
正如Aluan在評論中指出的那樣,這是使用上面的轉換器處理dynamic
的更巧妙的方法。 在您的Startup.cs
類中,添加以下內容:
services.AddControllers().AddJsonOptions(options =>
options.JsonSerializerOptions.Converters.Add(new DynamicJsonConverter()));
然后你不必在你的控制器中做任何愚蠢的事情。 您可以將 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();
}
好多了!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.