web-dev-qa-db-ja.com

JsonSerializer.Deserializeが失敗する

コードを検討してください...

_using System;
using System.Text.Json;

public class Program
{
    public static void Main()
    {
        int id = 9;
        string str = "{\"id\": " + id + "}";
        var u = JsonSerializer.Deserialize<User>(str);
        Console.WriteLine($"User ID: {u.Id}, Correct: {id == u.Id}");  // always 0/init/default value
    }
}


public class User {
    public int Id { get; set; }
}
_

データがUserオブジェクトに正しく逆シリアル化されないのはなぜですか?また、システムの問題である場合に備えて、 DotNetFiddle で動作を確認しました。例外はスローされません。

私の実際の実装は、return Created("user", newUser)の後に_[ApiController]_の_[HttpPost]_アクションから読み取られます。これは、MVC/Razorプロジェクトで__httpClient.PostAsync_を介して呼び出されます。 CreatedPostAsyncの呼び出しに返されたときに値が正しいことを確認しましたが、応答本文から解析された値にはデフォルト値のみが含まれています(実際のIDはGuid)。

StringContentのエンコードがApiControllerに投稿されているため、これはUTF8関連の問題である可能性があると最初に思いました。 UTF8逆シリアル化が参照されています here ですが、HttpContentのIO.StreamからReadOnlySpanまたは_Utf8JsonReader_に取得するのに問題がありました。

検索中に このプロジェクト を見つけたので、期待どおりに機能するはずです。

3
t.j.

あなたの問題は、_System.Text.Json_がデフォルトで大文字と小文字を区別するため、_"id": 9_(すべて小文字)がIdプロパティにマップされないことです。 docs から:

大文字と小文字を区別しないプロパティマッチング

デフォルトでは、逆シリアル化は、JSONとターゲットオブジェクトプロパティの間で大文字と小文字を区別するプロパティ名の一致を検索します。その動作を変更するには、 _JsonSerializerOptions.PropertyNameCaseInsensitive_trueに設定します。

_var options = new JsonSerializerOptions
{
    PropertyNameCaseInsensitive = true,
};
var weatherForecast = JsonSerializer.Deserialize<WeatherForecast>(jsonString, options);
_

だからあなたもそれをする必要があります:

_var u = JsonSerializer.Deserialize<User>(str, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
_

デモフィドル#1 ここ

asp.net core 3でjsonシリアライザー設定を設定するには?に示すように、ASP.NET Core 3.0で起動時にオプションを構成できます。

_services.AddControllers().AddJsonOptions(options =>
{
    options.PropertyNameCaseInsensitive = true;
});
_

または、モデルに [JsonPropertyName("id")] を適用することもできます。

_public class User {
    [JsonPropertyName("id")]
    public int Id { get; set; }
}
_

デモフィドル#2 ここ

4
dbc

mr5 のおかげで-- チャットでの大文字小文字の問題だと示唆

TitleCase( "Id")を使用するように文字列を変更すると、問題が解決します。

私はチケットを提出している最中で、 おそらく関連する問題コメント別の問題 につながり、ドキュメントにつながります ソリューション

var options = new JsonSerializerOptions();
options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;

オプションを使用して、問題を解決します...

string str = "{\"id\": " + id + "}";
var options = new JsonSerializerOptions();
options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
var u = JsonSerializer.Deserialize<User>(str, options);

他の誰かを助ける場合に備えて、これをすべてそのままにしておきます。

1
t.j.

ConfigureServicesStartup.cs

services.AddControllers()
        .AddJsonOptions(o => {
            o.JsonSerializerOptions.PropertyNamingPolicy=JsonNamingPolicy.CamelCase;
            o.PropertyNameCasInsensitive=true
        });
0
R.ali