Čeština v JSONu se nezobrazuje korektně

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Milan Obrtlík
Člen | 50
+
0
-

Jak můžu poslat české znaky přes JSON?
Nyní posílám takto:

<?php

namespace App\Presenters;

use Nette;

class HomepagePresenter extends Nette\Application\UI\Presenter {

    public function renderDefault() {
        $this->payload->test = "Řáďící číšňík";
        $this->sendPayload();
    }

}

V prohlížeči (Chrome 48) se mi zobrazí {"test":"ŘáďĂcĂ ÄŤĂšňĂk"}
ale v ladících nástrojích se to ukazuje korektně.

CZechBoY
Člen | 3608
+
0
-

A jak to vykreslujes? Mas tam spravne kodovani?

Milan Obrtlík
Člen | 50
+
0
-

Je to čistá „instalace“ nette/webproject pomocí composeru. Jediné dva přidané řádky jsou ty s tím $this.
To je všechno co vím.

CZechBoY
Člen | 3608
+
0
-

V cem to zobrazujes? V sablone? Je tam nastaveny stejny kodovani utf-8?

Milan Obrtlík
Člen | 50
+
0
-

$this->sendPayload() ukončí okamžitě presenter a odešle se jenom JSON (žádná šablona se nekreslí). Nevím kde mám nastavit kódování na UTF-8.

Kód

<?php

namespace App\Presenters;

use Nette;

class HomepagePresenter extends Nette\Application\UI\Presenter {

    public function renderDefault() {
        echo json_encode(["test"=>"Řádící číšňík"]);
        $this->terminate();
    }

}

vypíše v prohlížeči {"test":"\u0158\u00e1d\u00edc\u00ed \u010d\u00ed\u0161\u0148\u00edk"}

Mysteria
Člen | 797
+
+3
-
$this->sendResponse(new \Nette\Application\Responses\JsonResponse($data, 'application/json; charset=utf-8'));
Milan Obrtlík
Člen | 50
+
0
-

@Mysteria to rozsekl!

Mysteria
Člen | 797
+
0
-

Protože jsem to shodou okolností před pár dny taky řešil. :) Používal jsem kratší $this->sendJson($data), ale problém je, že tady ta metoda nemá jako volitelný parametr nastavení content type, takže jsem musel použít tuhle delší variantu.

pata.kusik111
Člen | 78
+
0
-

Když jsme u toho, tak json_encode($data, JSON_UNESCAPED_UNICODE) od PHP5.4

Milan Obrtlík
Člen | 50
+
0
-

@Mysteria tak zkrátit se to vždycky, horší je najít to, aby bylo co zkracovat
@pata.kusik111 json_encode($data, JSON_UNESCAPED_UNICODE) funguje taky, ale jak pak korektně ukončíš životní cyklus presenteru?

pata.kusik111
Člen | 78
+
0
-

Podědím a přepíši JsonResponse. To řešení od @Mysteria je bug, který by neměl fungovat. Stačí se podívat jak je JsonResponse napsaný. V nové třídě pak přepíši z JsonResponse tuhle část na echo Nette\Utils\Json::encode($this->payload, JSON_UNESCAPED_UNICODE);.

Samozřejmě, já jsem na druhou stranu strašný puritán a chápu, že takové řešení není zrovna z těch nejpraktičtějších…

Mysteria
Člen | 797
+
+1
-

@pata.kusik111: Co konkrétně vidíš za bug na řádku, který říká jenom to, že buď si zadáš vlastní content type nebo se použije výchozí?

@pata.kusik111:

$this->terminate();

Editoval Mysteria (19. 2. 2016 16:29)

pata.kusik111
Člen | 78
+
+2
-

Original:

@Mysteria moje chyba. Měl jsem za to, že charset má mít vlastní header. A źe se jen zneužívá řetězení pomocí středníku. Máš to samozřejmě naprosto správně. No jo už je víkend a nemyslí mi to.

Edited:

@Mysteria je to nestandardní chování, které funguje i když by nemělo. Do konstruktoru by měl přijít je MIME type. Protože:
JsonResponse::send se ten content type nastavuje. do Nette\Http\IResponse::setContentType. Ale jenom jako první parametr, ne jako oba parametry. Viz API dokumentace IHttpResponse. Opravdu to funguje bugem, ale ten bug je tady, kde to dovoluje nastavit charset jen s pomocí contentType a charset = NULL.

Takže „čisté/správné (jakkoli chcete říkat tomu zbytečně složitému řešení)“ řešení je přetížit JsonResponse::send na:

public function send(Nette\Http\IRequest $httpRequest, Nette\Http\IResponse $httpResponse)
 {
     $httpResponse->setContentType($this->contentType, 'utf-8');
     $httpResponse->setExpiration(FALSE);
     echo Nette\Utils\Json::encode($this->payload);
 }

Editoval pata.kusik111 (19. 2. 2016 16:58)

Mysteria
Člen | 797
+
0
-

Jo, už to vidím. Máš pravdu. :) Teď už jenom záleží na tom, kdo si co vybere.

pata.kusik111
Člen | 78
+
+1
-

Napsal jsem issue na GitHub.

Milan Obrtlík
Člen | 50
+
0
-

@Mysteria $this->terminate() sice presenter ukončí, ale Tracy se pořád objevuje – to je poněkud nežádoucí pro JSON.

@pata.kusik111 paráda, přetížil jsem JsonResponse::send tím ‚UTF-8‘ a už můžu zase používat $this->sendPayload! Boží!

Asi si budu trochu odporovat (minulou větou jsem vynášel $this->sendPayload do nebes), ale dá se v Nette nastavit aby se mi automaticky posílal JSON bez toho, abych nemusel pokaždé psát $this->sendPayload? Úplně kompletně celá aplikace bude vždy odpovídat jenom pomocí JSONu.

Editoval Milan Obrtlík (19. 2. 2016 18:43)

David Grudl
Nette Core | 8138
+
0
-

Použij sendJson($data)