shuhelohelo’s blog

Xamarin.Forms多めです.

Xamarin.FormsでSystem.Text.JSONでJSONファイルからデシリアライズするときのメモ

https://codeburst.io/working-with-json-in-net-core-3-2fd1236126c1codeburst.io

ここでは予めデシリアライズ先の型を用意して,Embedded resourceに指定したJSONファイルから読み込んだデータをデシリアライズする手順を示す.

System.Text.Jsonをインストール

Nugetからインストールする.

f:id:shuhelohelo:20200625194357p:plain

Jsonデータからクラスを生成する.

既存のWebAPIからデータをJSON形式で受け取る場合,そのJSONデータからデシリアライズ先のクラスを生成することができる.

WebAPIが返すJSONデータをまるっとコピーして,Visual StudioのメニューからEdito -> Paste Special -> Paste JSON as classesを選択すると,クラスが生成される.

JSON:

[
  {
    "id": 1,
    "first_name": "Danell",
    "last_name": "Hawksworth",
    "email": "dhawksworth0@upenn.edu",
    "gender": "Female",
    "ip_address": "81.48.89.94"
  },
  {
    "id": 2,
    "first_name": "Cob",
    "last_name": "Chapiro",
    "email": "cchapiro1@posterous.com",
    "gender": "Male",
    "ip_address": "122.16.10.192"
  },
  {
    "id": 3,
    "first_name": "Helli",
    "last_name": "Fairholme",
    "email": "hfairholme2@springer.com",
    "gender": "Female",
    "ip_address": "124.131.30.108"
  }
]

生成されたC#のクラス

    public class Rootobject
    {
        public Class1[] Property1 { get; set; }
    }

    public class Class1
    {
        public int id { get; set; }
        public string first_name { get; set; }
        public string last_name { get; set; }
        public string email { get; set; }
        public string gender { get; set; }
        public string ip_address { get; set; }
    }

シリアライズにこれをそのまま使っても良いが,Class1などになっているので適切な名前にに変更しておくとよい.

また,プロパティ名はJSONデータで使用されている名前がそのまま使われるので,C#のコーディング作法とは異なる場合がほとんどである.

プロパティ名を変更しただけでは,JSONデータとC#クラスの間で対応付けができなくなってしまうので,JsonPropertyName属性を使うことで,これを解決する.

    public class Rootobject
    {
        public Person[] People { get; set; }
    }

    public class Person
    {
        [JsonPropertyName("id")]
        public int Id { get; set; }
        [JsonPropertyName("first_name")]
        public string FirstName { get; set; }
        [JsonPropertyName("last_name")]
        public string LastName { get; set; }
        [JsonPropertyName("email")]
        public string Email { get; set; }
        [JsonPropertyName("gender")]
        public string Gender { get; set; }
        [JsonPropertyName("ip_address")]
        public string IpAddress { get; set; }
    }

このように各プロパティにJsonPropertyName属性でJSONデータにおける名前と,それに対応するC#のプロパティを明示する.

シリアライズする際に,日本語が文字コードになってしまうのですが,これについてはJsonSerializerOptionsを使います.

            var options = new JsonSerializerOptions
            {
                Encoder = JavaScriptEncoder.Create(UnicodeRanges.All),
            };

シリアライズ

ファイルから読み込む場合はこんな感じ.この例は,プロジェクトにEmbedded resourceとして追加したJSONファイルを読み込んでデシリアライズするとき.

            var assembly = Assembly.GetExecutingAssembly();
            using var stream = assembly.GetManifestResourceStream("XFCollectionViewGrouping.Data.PeopleData.json");

            var people = await System.Text.Json.JsonSerializer.DeserializeAsync<Person[]>(stream);

コメントつきのJSONをデシリアライズする場合は,以下のようにします.

shuhelohelo.hatenablog.com

JsonSerializerOptionsで設定できること

docs.microsoft.com

個人的注目 プロパティ 説明
AllowTrailingCommas 逆シリアル化される JSON ペイロード内でオブジェクトまたは配列の JSON 値の一覧の終わりにある余分なコンマが許可 (および無視) されるかどうかを示す値を取得または設定します。
Converters 登録されたユーザー定義のコンバーターの一覧を取得します。
DefaultBufferSize 一時バッファーの作成時に使用する、既定のバッファー サイズ (バイト単位) を取得または設定します。
DictionaryKeyPolicy IDictionary キーの名前を、camel 形式などの別の形式に変換するために使用されるポリシーを取得または設定します。
Encoder 文字列をエスケープするときに使用するエンコーダーを取得または設定します。既定のエンコーダーを使用する場合は null を設定します。
IgnoreNullValues シリアル化および逆シリアル化の間に null 値を無視するかどうかを決定する値を取得または設定します。 既定値は false です。
IgnoreReadOnlyProperties シリアル化中に読み取り専用プロパティを無視するかどうかを決定する値を取得します。 既定値は false です。
MaxDepth JSON をシリアル化または逆シリアル化するときに許容される最大の深さを取得または設定します。既定値は 0 で、最大の深さが 64 であることを示します。
PropertyNameCaseInsensitive 逆シリアル化中に、プロパティの名前で大文字と小文字を区別しない比較が使用されるかどうかを決定する値を取得または設定します。 既定値は false です。
PropertyNamingPolicy オブジェクトのプロパティの名前を、キャメルケース形式などの別の形式に変換するために使用されるポリシーを指定する値を取得または設定するか、プロパティ名を変更しない場合は null にします。
ReadCommentHandling 逆シリアル化中にコメントを処理する方法を定義する値を取得または設定します。
WriteIndented JSON で整形出力を使用する必要があるかどうかを定義する値を取得または設定します。 既定では、JSON は余分な空白なしでシリアル化されます。