---
title: 'Veri Biçimleri'
source: 'https://academia.sh/tr/kurslar/php-web/veri-bicimleri'
course: 'Web ile PHP: Oturum, Veri ve Güvenlik'
language: tr
updated: '2026-10-21T05:03:37+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - "JSON, XML ve CSV metnini PHP'de ayrıştırmak ve geçersiz JSON'da JsonException yakalamak"
    - 'Ortağın aynı alanı dizge ya da farklı adla yazmasının sonucu değiştirdiğini ölçmek'
    - 'XML ve CSV değerlerinin metin olarak geldiğini, tipin ayrıştırıcıya değil koda ait olduğunu ayırt etmek'
    - "Kendi ürettiğimiz JSON'daki sayı gösteriminin sunucunun seçimi olduğunu göstermek"
---

# Veri Biçimleri

Ortaktan gelen JSON, XML ve CSV metni ayrıştırılır; ortak aynı alanı farklı yazdığında sonucu kimin değiştirebildiği ölçülür ve kendi yanıtımızdaki sayı gösteriminin kimin seçimi olduğu gösterilir.

Sorguların sayısı da metni de elimizdeydi. Ama bir uygulama yalnız kendi veritabanıyla konuşmaz; dışarıdaki bir ortaktan da veri alır ve bu veri JSON, XML ya da CSV olarak gelir. Biçimi ortak belirler. Soru şudur: ortağın verisi biçim değiştirirse ne olur?

Bu dersin ölçü ekseni yine sonucun sahibidir. Karar sırası değişmez: istemci, üçüncü taraf, ortam; hiçbiri değiştiremiyorsa sunucu. Ağırlıklı taraf üçüncü taraftır: uygulamanın bağlandığı ortak, kodun dışında kalan ve bağlanılan tek taraftır. Ortaktan gelen metin ağdan alınmaz; bu derste sabit bir dizge olarak koda yazılır ve ağa çıkılmaz. Çekirdek dosya aynen gelir.

```php
<?php
// taraf.php — bu sonucu kim değiştirebiliyor?
declare(strict_types=1);

// Kodun dışındaki taraflar, karar sırasıyla: her istek, her dış çağrı, her dağıtım.
const DIS_TARAFLAR = ['istemci', 'üçüncü taraf', 'ortam'];

/** Sonucu bir kez sapmasız, sonra her dış tarafın sapmasıyla ayrı ayrı hesaplar. */
function sina(callable $sonuc, array $sapmalar): array {
    $taban = $sonuc([]);
    $degisti = [];
    foreach (DIS_TARAFLAR as $taraf) {
        if (array_key_exists($taraf, $sapmalar)) {
            $degisti[$taraf] = $sonuc([$taraf => $sapmalar[$taraf]]) !== $taban;
        }
    }
    return $degisti;
}

/** Sonucu değiştirebilen ilk dış taraf; hiçbiri değiştiremiyorsa sunucu. */
function taraf(array $degisti): string {
    foreach (DIS_TARAFLAR as $t) {
        if ($degisti[$t] ?? false) return $t;
    }
    return 'sunucu';
}

function tarafRaporu(string $ad, callable $sonuc, array $sapmalar): string {
    $degisti = sina($sonuc, $sapmalar);
    $satirlar = [];
    foreach ($degisti as $t => $d) $satirlar[] = $t . ($d ? ' değiştirdi' : ' değiştiremedi');
    $sonTaraf = taraf($degisti);
    echo "$ad → $sonTaraf\n    ", implode(' · ', $satirlar), "\n";
    return $sonTaraf;
}
```
**VE17.** Ortağın gönderdiği metin, bir fonksiyonun ürettiği sabit bir dizgedir; üç biçimde aynı iki ürünü anlatır: kodu `k1` ve `k2`, fiyatları `12.5` ve `8`. **VE18.** Ortağın sapması aynı alanı farklı yazmasıdır: fiyatı sayı yerine dizge olarak gönderir ya da alan adını `fiyat` yerine `ucret` yazar. **VE19.** Kod, ortağın verisini doğrulamadan olduğu gibi okur; doğrulama Güvenlik konusunun işidir. **VE20.** Sonuç, ayrıştırılan fiyat listesinin JSON gösterimidir.

## Üç Biçim

JSON (JavaScript Object Notation), iç içe diziler ve nesneler taşıyan bir metin biçimidir. PHP'de `json_decode()` onu diziye çevirir. Geçersiz metinde varsayılan davranış sessizce `null` döndürmektir; `JSON_THROW_ON_ERROR` bayrağı bunu bir `JsonException` haline getirir ve hata gözden kaçmaz. XML, etiketlerle kurulu bir ağaçtır; `simplexml_load_string()` onu bir nesneye çevirir. CSV, satırlara ve virgüllerle ayrılmış alanlara dayanır; `str_getcsv()` bir satırı diziye böler. Üçünde de ortak sınır aynıdır: kod, ayrıştırılan şeyin biçimini kendisi bilmek zorundadır.

Aşağıdaki dosya ortağın üç biçimdeki metnini üretir ve her biri için fiyatları okuyan bir ayrıştırıcı tanımlar. Çıktısı yoktur, yalnız diske yazılır.

```php
<?php
// ortak.php — ortağın üç biçimi ve fiyatları okuyan ayrıştırıcılar
declare(strict_types=1);

function ortakJson(?string $sapma = null): string {
    $birinci = $sapma === 'dizge' ? '"12.5"' : '12.5';
    $ikinci = $sapma === 'dizge' ? '"8"' : '8';
    $alan = $sapma === 'alan' ? 'ucret' : 'fiyat';
    return '{"urunler":[{"kod":"k1","' . $alan . '":' . $birinci . '},{"kod":"k2","' . $alan . '":' . $ikinci . '}]}';
}

function ortakXml(): string {
    return '<urunler><urun kod="k1"><fiyat>12.5</fiyat></urun><urun kod="k2"><fiyat>8</fiyat></urun></urunler>';
}

function ortakCsv(): string {
    return "kod,fiyat\nk1,12.5\nk2,8";
}

function jsonFiyatlari(string $metin): array {
    $veri = json_decode($metin, true, flags: JSON_THROW_ON_ERROR);
    return array_map(fn(array $u) => $u['fiyat'] ?? null, $veri['urunler']);
}

function xmlFiyatlari(string $metin): array {
    $kok = simplexml_load_string($metin);
    $fiyatlar = [];
    foreach ($kok->urun as $urun) $fiyatlar[] = (string) $urun->fiyat;
    return $fiyatlar;
}

function csvFiyatlari(string $metin): array {
    $satirlar = explode("\n", $metin);
    array_shift($satirlar);
    return array_map(fn(string $satir) => str_getcsv($satir, escape: '')[1], $satirlar);
}
```

`str_getcsv()` çağrısındaki `escape: ''` bağımsız değişkeni, ters eğik çizginin kaçış karakteri sayılmasını kapatır; CSV'nin kendi kuralı yalnız tırnak işaretidir. Üç ayrıştırıcıyı çalıştıralım ve geçersiz JSON ile geçersiz XML'e bakalım.

```php
<?php
// bicimler.php — üç ayrıştırıcı ve geçersiz girdi
declare(strict_types=1);
require 'ortak.php';

echo 'json: ', json_encode(jsonFiyatlari(ortakJson())), "\n";
echo 'xml: ', json_encode(xmlFiyatlari(ortakXml())), "\n";
echo 'csv: ', json_encode(csvFiyatlari(ortakCsv())), "\n";

try {
    jsonFiyatlari('{"urunler":[');
} catch (JsonException $e) {
    echo 'geçersiz json: ', get_class($e), ', ileti: ', $e->getMessage(), "\n";
}

libxml_use_internal_errors(true);
echo 'geçersiz xml: ', var_export(simplexml_load_string('<urunler><urun>'), true), "\n";
```

```
json: [12.5,8]
xml: ["12.5","8"]
csv: ["12.5","8"]
geçersiz json: JsonException, ileti: Syntax error
geçersiz xml: false
```

JSON sayıları sayı olarak getirdi; XML ve CSV ise her değeri metin olarak. Bu fark ayrıştırıcıdan gelir ve ortağın kararı değildir: bir XML etiketinin içindeki `12.5`, biçim gereği her zaman metindir. Geçersiz JSON `JsonException` fırlattı; geçersiz XML ise hata yerine `false` döndürdü. İkisini de kodun kendisi denetlemek zorundadır.

## Ortak Aynı Alanı Farklı Yazarsa

Ortağın sapması, kodun beklediği biçimden küçük bir ayrılıktır. Fiyatı `12.5` yerine `"12.5"` yazar; ya da alanı `fiyat` yerine `ucret` diye adlandırır. İlk durumda kod hata vermez, yalnız dönen değerin tipi değişir. İkinci durumda alan bulunamaz ve kod `null` okur. İkisi de ortağın elindedir.

```php
<?php
// ortaksonuc.php — fiyatları kim değiştirebiliyor?
declare(strict_types=1);
require 'taraf.php';
require 'ortak.php';

function fiyatlar(array $s): string {
    return json_encode(jsonFiyatlari(ortakJson($s['üçüncü taraf'] ?? null)));
}

tarafRaporu('fiyatlar, dizge', 'fiyatlar', ['üçüncü taraf' => 'dizge']);
tarafRaporu('fiyatlar, alan adı', 'fiyatlar', ['üçüncü taraf' => 'alan']);
```

```
fiyatlar, dizge → üçüncü taraf
    üçüncü taraf değiştirdi
fiyatlar, alan adı → üçüncü taraf
    üçüncü taraf değiştirdi
```

Her iki sapmada da sonuç üçüncü tarafın elindedir. Dizge durumunda fiyatlar sayı olmaktan çıktı; çıktıda tırnak içinde görünmeleri bunu gösterir ve `strict_types` altında sayı bekleyen bir fonksiyona verilmeleri artık tip uyuşmazlığı olur. Alan adı durumunda fiyatların hiçbiri okunamadı. Kod aynı kaldı; ortağın metni değişti. Bu yüzden ayrıştırmanın sonucu, ortağın biçimine uyulduğu sürece doğrudur; uyum ortağın sözüne bağlıdır.

## Ayrıştırıcı Ne Garanti Eder, Ne Etmez

CSV'de bir alan virgül içeriyorsa çift tırnağa alınır. Ortak bu kuralı uygularsa ayrıştırıcı alanı bütün tutar; uygulamazsa satır beklenenden fazla sütuna bölünür. Aynı satırı iki biçimde okuyalım.

```php
<?php
// tirnak.php — virgül içeren CSV alanı
declare(strict_types=1);

$tirnakli = 'k3,"Kalem, mavi",4.5';
$tirnaksiz = 'k3,Kalem, mavi,4.5';
echo 'tırnaklı: ', json_encode(str_getcsv($tirnakli, escape: ''), JSON_UNESCAPED_UNICODE), "\n";
echo 'tırnaksız: ', json_encode(str_getcsv($tirnaksiz, escape: ''), JSON_UNESCAPED_UNICODE), "\n";
```

```
tırnaklı: ["k3","Kalem, mavi","4.5"]
tırnaksız: ["k3","Kalem"," mavi","4.5"]
```

Tırnaklı satır üç alan verdi, tırnaksız satır dört. Ayrıştırıcı iki durumda da doğru çalıştı; fark ortağın yazdığı metinden geldi. Aynı ayrım JSON ve XML için de geçerlidir: ayrıştırıcı biçimin kurallarını uygular, ortağın o kurallara uyup uymadığına karar vermez. Bu yüzden üç ayrıştırıcının hiçbiri fiyatın sayı olacağını önceden bilemez; bunu bilen yalnız ortağın sözleşmesidir ve sözleşme kodun dışındadır.

## Sınırlayıcı Ölçüm

Şimdi yön tersine dönsün: ortaktan aldığımız bir değeri kendi yanıtımızda JSON olarak geri verelim. Ortağın gönderdiği indirim `1.0` ya da `1` olabilir; `json_decode()` birini ondalıklı, ötekini tam sayı olarak getirir. Yanıtı `json_encode()` ile üretirken PHP varsayılan olarak `1.0` değerini `1` diye yazar; `JSON_PRESERVE_ZERO_FRACTION` bayrağı ondalık kısmı korur ve `1.0` yazar. Bu gösterimi seçen biziz.

```php
<?php
// yanit.php — kendi yanıtımızdaki sayı gösterimi
declare(strict_types=1);
require 'taraf.php';

echo 'bayraksız: ', json_encode(1.0), "\n";
echo 'bayrakla: ', json_encode(1.0, JSON_PRESERVE_ZERO_FRACTION), "\n";

function yanit(array $s, int $bayrak, bool $zorla): string {
    $metin = $s['üçüncü taraf'] ?? '{"indirim":1.0}';
    $indirim = json_decode($metin, true, flags: JSON_THROW_ON_ERROR)['indirim'];
    return json_encode(['indirim' => $zorla ? (float) $indirim : $indirim], $bayrak);
}

$sapma = ['üçüncü taraf' => '{"indirim":1}'];
tarafRaporu('varsayılan bayrak', fn(array $s) => yanit($s, 0, false), $sapma);
tarafRaporu('bayrak, ortağın gösterimi', fn(array $s) => yanit($s, JSON_PRESERVE_ZERO_FRACTION, false), $sapma);
tarafRaporu('bayrak ve float dönüşümü', fn(array $s) => yanit($s, JSON_PRESERVE_ZERO_FRACTION, true), $sapma);
```

```
bayraksız: 1
bayrakla: 1.0
varsayılan bayrak → sunucu
    üçüncü taraf değiştiremedi
bayrak, ortağın gösterimi → üçüncü taraf
    üçüncü taraf değiştirdi
bayrak ve float dönüşümü → sunucu
    üçüncü taraf değiştiremedi
```

Varsayılan bayrakla yanıt, ortağın `1` ya da `1.0` yazmasından bağımsız aynı çıktı: sonuç sunucuda. Yalnız bayrak eklenince yanıt ortağın yazdığı gösterimi taşımaya başlar ve sonuç üçüncü tarafa döner. Bayrağa ek olarak değer `float`'a çevrilince yanıtın gösterimi yine tamamen bizim elimizde. Yanıtta sayının nasıl görüneceği sunucunun seçimidir; ortak yalnız bizim ona bıraktığımız kadarını belirler.

## Özet

- JSON, XML ve CSV ayrı ayrıştırıcılarla okunur; `JSON_THROW_ON_ERROR` geçersiz JSON'u `JsonException`'a çevirir, `str_getcsv()` çağrısında `escape: ''` verilir.
- XML ve CSV değerleri metin olarak gelir; JSON sayıları sayı olarak gelir. Tipi belirleyen ayrıştırıcıdır, ortak değildir.
- Ortak aynı alanı dizge ya da başka adla yazarsa fiyat listesi değişir; bu derste taraf üçüncü taraftır.
- Kendi yanıtımızdaki sayı gösterimi `json_encode()` bayrağı ve tip dönüşümüyle belirlenir ve sunucunun seçimidir.
- Aynı ortak verisi bir sonuçta üçüncü tarafa, bir başka sonuçta sunucuya ait olabilir.

## Sonraki Adım

Ortaktan veriyi bir kez ayrıştırdık; ama ortağa ulaşmak için önce bir istek göndermek gerekir. İstek ve yanıt arasında zaman aşımı da vardır. Sonraki ders, servis yanıt vermezse istemcinin ne yaptığını ele alır.
