# Kod &#199;&#246;z&#252;c&#252;ler

<div id="introduction"></div>

## Giri&#351;

Kod &#231;&#246;z&#252;c&#252;ler, Nylo taraf&#305;ndan tan&#305;t&#305;lan ve verileri nesnelere veya s&#305;n&#305;flara d&#246;n&#252;&#351;t&#252;rmenize olanak sa&#287;layan bir kavramd&#305;r.
Kod &#231;&#246;z&#252;c&#252;leri b&#252;y&#252;k olas&#305;l&#305;kla [a&#287; i&#351;lemleri](/docs/7.x/networking) s&#305;n&#305;f&#305;yla &#231;al&#305;&#351;&#305;rken veya Nylo'daki `api` yard&#305;mc&#305;s&#305;n&#305; kullanmak istedi&#287;inizde kullanacaks&#305;n&#305;z.

> Varsay&#305;lan olarak, kod &#231;&#246;z&#252;c&#252;lerin konumu `lib/config/decoders.dart` dosyas&#305;d&#305;r

decoders.dart dosyas&#305; iki de&#287;i&#351;ken i&#231;erecektir:
- [modelDecoders](#model-decoders) - T&#252;m model kod &#231;&#246;z&#252;c&#252;lerinizi y&#246;netir
- [apiDecoders](#api-decoders) - T&#252;m API kod &#231;&#246;z&#252;c&#252;lerinizi y&#246;netir

<div id="model-decoders"></div>

## Model Kod &#199;&#246;z&#252;c&#252;ler

Model kod &#231;&#246;z&#252;c&#252;ler Nylo'da yenidir, veri y&#252;klerini model temsillerine d&#246;n&#252;&#351;t&#252;rmenin bir yolunu sa&#287;larlar.

`network()` yard&#305;mc&#305; metodu, hangi kod &#231;&#246;z&#252;c&#252;n&#252;n kullan&#305;laca&#287;&#305;n&#305; belirlemek i&#231;in <b>config/decoders.dart</b> dosyan&#305;zdaki `modelDecoders` de&#287;i&#351;kenini kullanacakt&#305;r.

&#304;&#351;te bir &#246;rnek.

`network` yard&#305;mc&#305;s&#305;n&#305;n modelDecoders'&#305; nas&#305;l kulland&#305;&#287;&#305; a&#351;a&#287;&#305;dad&#305;r.

```dart
class ApiService extends NyApiService {
  ApiService({BuildContext? buildContext}) 
        : super(buildContext, decoders: modelDecoders);

  @override
  String get baseUrl => "https://jsonplaceholder.typicode.com";

  Future<User?> fetchUsers() async {
    return await network<User>(
        request: (request) => request.get("/users"),
    );
  }
...
```

`fetchUsers` metodu, istekten gelen y&#252;k&#252; otomatik olarak bir `User` nesnesine d&#246;n&#252;&#351;t&#252;recektir.

Bu nas&#305;l &#231;al&#305;&#351;&#305;r?

A&#351;a&#287;&#305;daki gibi bir `User` s&#305;n&#305;f&#305;n&#305;z var.

```dart
class User {
  String? name;
  String? email;

  User.fromJson(dynamic data) {
    this.name = data['name'];
    this.email = data['email'];
  }

  toJson()  => {
    "name": this.name,
    "email": this.email
  };
}
```

Yukar&#305;dan g&#246;rebilece&#287;iniz gibi bu s&#305;n&#305;f&#305;n s&#305;n&#305;f&#305; ba&#351;latmam&#305;z&#305; sa&#287;layan bir `fromJson` metodu vard&#305;r.

Bu s&#305;n&#305;f&#305; a&#351;a&#287;&#305;daki metodu &#231;a&#287;&#305;rarak ba&#351;latabiliriz.

```dart
User user = User.fromJson({'name': 'Anthony', 'email': 'agordon@mail.com'});
```

&#350;imdi, kod &#231;&#246;z&#252;c&#252;lerimizi kurmak i&#231;in a&#351;a&#287;&#305;dakini yapmam&#305;z gerekiyor.

<b>Dosya:</b> config/decoders.dart
```dart
final modelDecoders = {
  List<User>: (data) => List.from(data).map((json) => User.fromJson(json)).toList(),

  User: (data) => User.fromJson(data),

  // ...
};
```

modelDecoders dosyas&#305;nda, anahtar olarak `Type` sa&#287;lamam&#305;z ve de&#287;erde yukar&#305;daki &#246;rnekteki gibi d&#246;n&#252;&#351;&#252;m&#252; yapmam&#305;z gerekir.

`data` arg&#252;man&#305;, API iste&#287;inden gelen y&#252;k&#252; i&#231;erecektir.

<div id="typed-decoders"></div>

## Tipli Kod &#199;&#246;z&#252;c&#252;ler

<div class="ny-doc-strip">
<span class="ny-doc-strip-label">Gereksinimler</span>
<span class="ny-doc-strip-item">Nylo 7.5.0+</span>
<span class="ny-doc-strip-dot"></span>
<span class="ny-doc-strip-item">nylo_support 7.37.0+</span>
</div>

`decoders([...])`, `modelDecoders` map'inizi bir listeden olu&#351;turur. `Decode(User.fromJson)` bir `User`'&#305; ve ayr&#305;ca bir `List<User>`'&#305;, ayr&#305; bir girdi gerektirmeden &#231;&#246;zer:

```dart
final Map<Type, dynamic> modelDecoders = decoders([
  Decode(User.fromJson),
  Decode(Order.fromJson, from: 'data'),
]);
```

Modeli `{"data": {...}}` gibi sarmalanm&#305;&#351; bir g&#246;vdenin i&#231;inden okumak i&#231;in `from` kullan&#305;n. `'data.user'` gibi noktal&#305; bir anahtar daha derinden okur; liste i&#231;in ise listenin kendisi `from` i&#231;inden okunur.

`Decode`, `dynamic` veya `Map<String, dynamic>` kabul eden bir `fromJson` al&#305;r. Bir closure i&#231;in parametresinin t&#252;r&#252;n&#252; belirtin:

```dart
Decode((dynamic json) => User.fromJson(json)),
```

`User: (data) => User.fromJson(data)` gibi `{...}` map'indeki closure kod &#231;&#246;z&#252;c&#252;ler &#231;al&#305;&#351;maya devam eder. &#304;kisi de bir `NyDecoder`'d&#305;r; `Decode` ve `OneOf` bu s&#305;n&#305;f&#305; geni&#351;letir. &#214;zel bir `NyDecoder<T>`, `decode(json, response, decoders)` metodunu uygular ve t&#252;m `NyResponse`'u g&#246;r&#252;r, b&#246;ylece durum kodunu veya ba&#351;l&#305;klar&#305; okuyabilir.

<div id="one-of"></div>

## OneOf

<div class="ny-doc-strip">
<span class="ny-doc-strip-label">Gereksinimler</span>
<span class="ny-doc-strip-item">Nylo 7.5.0+</span>
<span class="ny-doc-strip-dot"></span>
<span class="ny-doc-strip-item">nylo_support 7.37.0+</span>
</div>

`OneOf`, birden fazla bi&#231;im alabilen bir yan&#305;t&#305; &#231;&#246;zer. Payla&#351;&#305;lan &#252;st t&#252;r alt&#305;nda kaydedin ve bi&#231;imi g&#246;vdedeki bir alana, durum koduna veya kendi ko&#351;ullar&#305;n&#305;za g&#246;re se&#231;in:

```dart
final Map<Type, dynamic> modelDecoders = decoders([
  OneOf<LoginResult>.byKey('status', {
    'success': LoginSuccess.fromJson,
    'two_factor': TwoFactorRequired.fromJson,
  }, otherwise: (json) => LoginFailed(ApiError.fromJson(json))),
]);
```

`OneOf` ayr&#305;ca 4xx ve 5xx g&#246;vdelerini ve bir `List<T>`'&#305; &#246;&#287;e &#246;&#287;e &#231;&#246;zer. Tan&#305;mad&#305;&#287;&#305; bir bi&#231;im, yan&#305;t verisini null b&#305;rak&#305;r.

| Yap&#305;c&#305; | Bi&#231;imi &#351;una g&#246;re se&#231;er |
|-------------|--------------------|
| `OneOf.byKey(key, types, otherwise:)` | G&#246;vdedeki `key` de&#287;erine g&#246;re. `'data.type'` gibi noktal&#305; bir anahtar i&#231; i&#231;e bir alan&#305; okur |
| `OneOf.byStatus(types, otherwise:)` | Durum koduna g&#246;re. Anahtar `404` gibi bir kod veya `'4xx'` ya da `'40x'` gibi bir desen olabilir |
| `OneOf.byJson(types, otherwise:)` | Her biri g&#246;vdeyi ve yan&#305;t&#305; alan kendi ko&#351;ullar&#305;n&#305;za g&#246;re. True d&#246;nd&#252;ren ilk ko&#351;ul kazan&#305;r |
| `OneOf(resolve)` | G&#246;vdeyi ve yan&#305;t&#305; al&#305;p de&#287;eri veya null d&#246;nd&#252;ren bir fonksiyon |

Durum koduna g&#246;re:

```dart
OneOf<OrderResult>.byStatus({
  200: OrderPlaced.fromJson,
  404: OrderNotFound.fromJson,
  '4xx': (json) => OrderRejected(ApiError.fromJson(json)),
}),
```

&#214;nce tam e&#351;le&#351;en kod, ard&#305;ndan en az `x` i&#231;eren desen kazan&#305;r.

Kendi ko&#351;ullar&#305;n&#305;zla:

```dart
OneOf<SignUpResult>.byJson({
  (json, response) => response.statusCode == 200 && json['status'] == 'ok': SignUpComplete.fromJson,
  (json, response) => response.statusCode == 200 && json['status'] == 'verify': VerifyEmail.fromJson,
}),
```

Bir fonksiyonla:

```dart
OneOf<OrderResult>((json, response) => switch ((response.statusCode, json)) {
  (200, {'status': 'placed'}) => OrderPlaced.fromJson(json),
  (200, _) => OrderPending.fromJson(json),
  _ => null,
}),
```

Bir yan&#305;ttan bi&#231;imi `dataAs<X>()` ve `dataIs<X>()` ile okuyun; bkz. [NyResponse](/docs/7.x/networking#ny-response).

Metro, &#252;st t&#252;r&#252;, alt t&#252;rlerini ve `OneOf.byKey` girdisini sizin i&#231;in olu&#351;turur:

```bash
metro make:model login_result --one-of="success,two_factor"
```

Bkz. [OneOf modeli olu&#351;turma](/docs/7.x/metro#make-a-one-of-model).

<div id="api-decoders"></div>

## API Kod &#199;&#246;z&#252;c&#252;ler

API kod &#231;&#246;z&#252;c&#252;ler, `api` yard&#305;mc&#305; metodu &#231;a&#287;r&#305;l&#305;rken kullan&#305;l&#305;r.

```dart
loadUser() async {
    User user = await api<ApiService>((request) => request.fetchUser());
}
```

`api` yard&#305;mc&#305;s&#305;, generic'ler kullanarak do&#287;ru API Servisini e&#351;le&#351;tirecektir, b&#246;ylece servisinize eri&#351;mek i&#231;in a&#351;a&#287;&#305;daki yard&#305;mc&#305;y&#305; &#231;a&#287;&#305;rabilirsiniz.

```dart
await api<MyService>((request) => request.callMyMethod());
```

`api` yard&#305;mc&#305;s&#305;n&#305; kullanmadan &#246;nce, API Servisinizi <b>lib/config/decoders.dart > apiDecoders</b> i&#231;ine eklemeniz gerekecektir.

```dart
final Map<Type, dynamic> apiDecoders = {
  ApiService: ApiService(),

  // ...
};
```
