System.Text.JsonでDeserializeAnonymousType（匿名型にデシリアライズ）


## 匿名型にデシリアライズする
### Json.NET
Json.NET（Newtonsoft.Json）には匿名型にデシリアライズする`DeserializeAnonymousType`というメソッドがあります。
APIのレスポンスから欲しいデータだけをサクッと取りたい場合などに便利です。

```csharp
using Newtonsoft.Json;

var json = """
{
  "name": "山田太郎",
  "age": 30,
  "address": {
    "country": "日本",
    "city": "東京",
    "postalCode": "100-0001"
  },
  "hobbies": ["読書", "映画", "旅行"]
}

var item = JsonConvert.DeserializeAnonymousType(json, 
    new { name = "", address = new { country = "" }});
Console.WriteLine($"name={item.name}, country={item.address.country}");

//name=山田太郎, country=日本
```

### System.Text.Json
`System.Text.Json`には`DeserializeAnonymousType`に相当するメソッドはありませんが、下記の様のようなジェネリックメソッドで実現可能です。

#### ジェネリックメソッドの型推論を使う

```csharp
T? DeserializeAnonymousType<T>(string value, T _) => JsonSerializer.Deserialize<T>(value);
```
このメソッドでは、第２引数に渡されたオブジェクトの型を基に、型引数Tが推論されます。この機能により、型名を明示的に指定できない匿名型でも、JsonSerializer.Deserialize<T>メソッドを利用することが可能となります。




```csharp
using System.Text.Json;

var json = """
{
  "name": "山田太郎",
  "age": 30,
  "address": {
    "country": "日本",
    "city": "東京",
    "postalCode": "100-0001"
  },
  "hobbies": ["読書", "映画", "旅行"]
}
""";

static T? DeserializeAnonymousType<T>(string value, T _) => JsonSerializer.Deserialize<T>(value);

var item = DeserializeAnonymousType(json, 
    new { name = "", address = new { country = "" }, hobbies = new[] { "" } });

if (item != null)
{
  Console.WriteLine($"name={item.name}, country={item.address.country}, hobbies=({string.Join(",", item.hobbies)})");
}

//name=山田太郎, country=日本, hobbies=(読書,映画,旅行)

```


#### 配列の場合
ルートの要素が配列の場合も下記の様に書いてもいけますが

```csharp
var jsonArray = """
[
  {
    "name": "山田太郎",
    "age": 30,
    "address": {
      "country": "日本",
      "city": "東京",
      "postalCode": "100-0001"
    },
    "hobbies": ["読書", "映画", "旅行"]
  },
  {
    "name": "鈴木花子",
    "age": 25,
    "address": {
      "country": "日本",
      "city": "大阪",
      "postalCode": "530-0001"
    },
    "hobbies": ["音楽", "料理", "写真"]
  }
]
""";

var items2 = DeserializeAnonymousType(jsonArray, 
    new[] { 
       new { name = "", address = new { country = "" }, hobbies = new[] { "" } } 
    });
```

次の様に、渡す匿名型は単一のまま`JsonSerializer.Deserialize<T>`の型引数で対応する方がスッキリ書けます。

- 配列用
```csharp
IEnumerable<T> DeserializeAnonymousArray<T>(string value, T _) =>
    JsonSerializer.Deserialize<IEnumerable<T>>(value) ?? [];
```


```csharp
using System.Text.Json;

var jsonArray = """
[
  {
    "name": "山田太郎",
    "age": 30,
    "address": {
      "country": "日本",
      "city": "東京",
      "postalCode": "100-0001"
    },
    "hobbies": ["読書", "映画", "旅行"]
  },
  {
    "name": "鈴木花子",
    "age": 25,
    "address": {
      "country": "日本",
      "city": "大阪",
      "postalCode": "530-0001"
    },
    "hobbies": ["音楽", "料理", "写真"]
  }
]
""";

static IEnumerable<T> DeserializeAnonymousArray<T>(string value, T _) =>
    JsonSerializer.Deserialize<IEnumerable<T>>(value) ?? [];
    
var items = DeserializeAnonymousArray(jsonArray, 
    new { name = "", age = 0, address = new { city = "" } });
foreach (var item in items)
{
  Console.WriteLine($"name={item.name}, age={item.age}, city={item.address.city}");
}

//name=山田太郎, country=日本, hobbies=(読書,映画,旅行)
//name=鈴木花子, country=日本, hobbies=(音楽,料理,写真)

```