JSON

Existují i jiné programovací jazyky než Python.

Ostatní jazyky neumí pracovat s pythonními hodnotami. Budeš-li se chtít s takovými programy „domluvit” – předat jim nějaké informace ke zpracování nebo od nich dostat výsledky – musíš informace předávat v nějaké zjednodušené podobě.

Typy

Většina programovacích jazyků má nějaká čísla, nějaký druh seznamů, nějakou odrůdu řetězců a nějakou variaci na slovníky (nebo několik způsobů jak slovníky vytvořit). Dále má spousta jazyků způsob, jak zapsat True, False a None.

Tyhle základní typy většinou stačí na předání jakékoli informace v rozumně čitelné podobě, i když ne ve všech jazycích mají přesné ekvivalenty (třeba Python má dva základní druhy čísel – int a float). Často se proto v komunikaci omezíme na ně.

Kódování dat

Další problém je přenos dat: abys mohla informace zapsat na disk nebo přenést přes Internet, musíš je převést na sekvenci bytů (čísel od 0 do 255). Zjednodušeně řečeno, musíš je převést na řetězec.

Existuje spousta způsobů, jak zakódovat data do textu. Každý způsob se snaží najít vhodnou rovnováhu mezi čitelností pro lidi/počítače, délkou zápisu, bezpečností, možnostmi a rozšiřitelností. My už známe syntaxi Pythonu:

{
    'jméno': 'Anna',
    'město': 'Brno',
    'jazyky': ['čeština', 'angličtina', 'Python'],
    'věk': 26,
}

Jiný způsob zápisu dat je YAML:

jméno: Anna
město: Brno
jazyky:
  - čeština
  - angličtina
  - Python
věk: 26

Nebo třeba Bencode:

d6:jazykyl9:čeština11:angličtina6:Pythone4:věki26e6:město4:Brno6:jméno4:Annae

Existují i netextové formáty, jako Pickle 3:

}q(XjménoqXAnnaqXmÄtoqXBrnoqXjazykyq]q(X       ÄeÅ¡tinaqX
                                                          angliÄtinaXPythonq       eXvÄq
K▒u.

A nakonec uvedu JSON (z angl. Javascript Object Notation „zápis Javascriptových objektů”), který se pro svou jednoduchost rozšířil na Internetu nejvíc:

{
  "jméno": "Anna",
  "město": "Brno",
  "jazyky": ["čeština", "angličtina", "Python"],
  "věk": 26
}

Pozor na to, že ačkoli JSON vypadá podobně jako zápis v Pythonu, je to jiný formát s vlastními pravidly. Nezaměňuj je!

Aspoň ze začátku nedoporučuji JSON psát ručně; nech na počítači, aby dal na správné místo správné čárky a uvozovky.

JSON v Pythonu

Kódování objektů v JSONu je jednoduché: existuje modul json, jehož metoda loads načte data z řetězce:

import json

json_retezec = """
    {
      "jméno": "Anna",
      "město": "Brno",
      "jazyky": ["čeština", "angličtina", "Python"],
      "věk": 26
    }
"""

data = json.loads(json_retezec)
print(data)
print(data['město'])

A pak tu je metoda dumps, která naopak daná data zakóduje a vrátí řetězec:

>>> print(json.dumps(data))
{"v\u011bk": 26, "jm\u00e9no": "Anna", "jazyky": ["\u010de\u0161tina", "angli\u010dtina", "Python"], "m\u011bsto": "Brno"}

To, co vrátí jednoduché zavolání dumps(data) je vhodné pro počítačové zpracování; má-li výsledná data číst člověk, nastav ensure_ascii=False (aby se písmenka s diakritikou nekódovala pomocí \) a indent=2 (odsazení dvěma mezerami).

>>> print(json.dumps(data, ensure_ascii=False, indent=2))
{
  "věk": 26,
  "jméno": "Anna",
  "jazyky": [
    "čeština",
    "angličtina",
    "Python"
  ],
  "město": "Brno"
}

Kompletní popis modulu json – včetně funkcí na zápis/čtení přímo do/ze souborů – je v příslušné dokumentaci.

{
  "data": {
    "sessionMaterial": {
      "id": "session-material:2018/pyladies-ostrava-podzim:dict:1",
      "title": "JSON",
      "html": "\n          \n    \n\n    <h1>JSON</h1>\n<p>Existuj&#xED; i jin&#xE9; programovac&#xED; jazyky ne&#x17E; Python.</p>\n<p>Ostatn&#xED; jazyky neum&#xED; pracovat s pythonn&#xED;mi hodnotami.\nBude&#x161;-li se cht&#xED;t s takov&#xFD;mi programy &#x201E;domluvit&#x201D; &#x2013;\np&#x159;edat jim n&#x11B;jak&#xE9; informace ke zpracov&#xE1;n&#xED;\nnebo od nich dostat v&#xFD;sledky &#x2013;\nmus&#xED;&#x161; informace p&#x159;ed&#xE1;vat v n&#x11B;jak&#xE9; zjednodu&#x161;en&#xE9; podob&#x11B;.</p>\n<h2>Typy</h2>\n<p>V&#x11B;t&#x161;ina programovac&#xED;ch jazyk&#x16F; m&#xE1; n&#x11B;jak&#xE1; &#x10D;&#xED;sla, n&#x11B;jak&#xFD; druh seznam&#x16F;,\nn&#x11B;jakou odr&#x16F;du &#x159;et&#x11B;zc&#x16F; a n&#x11B;jakou variaci na slovn&#xED;ky\n(nebo n&#x11B;kolik zp&#x16F;sob&#x16F; jak slovn&#xED;ky vytvo&#x159;it).\nD&#xE1;le m&#xE1; spousta jazyk&#x16F; zp&#x16F;sob, jak zapsat\n<code>True</code>, <code>False</code> a <code>None</code>.</p>\n<p>Tyhle z&#xE1;kladn&#xED; typy v&#x11B;t&#x161;inou sta&#x10D;&#xED; na p&#x159;ed&#xE1;n&#xED;\njak&#xE9;koli informace v&#xA0;rozumn&#x11B; &#x10D;iteln&#xE9; podob&#x11B;,\ni kdy&#x17E; ne ve v&#x161;ech jazyc&#xED;ch maj&#xED; p&#x159;esn&#xE9; ekvivalenty\n(t&#x159;eba Python m&#xE1; dva z&#xE1;kladn&#xED; druhy &#x10D;&#xED;sel &#x2013; <code>int</code> a <code>float</code>).\n&#x10C;asto se proto v&#xA0;komunikaci omez&#xED;me na n&#x11B;.</p>\n<h2>K&#xF3;dov&#xE1;n&#xED; dat</h2>\n<p>Dal&#x161;&#xED; probl&#xE9;m je p&#x159;enos dat:\nabys mohla informace zapsat na disk nebo p&#x159;en&#xE9;st\np&#x159;es Internet, mus&#xED;&#x161; je p&#x159;ev&#xE9;st na sekvenci <em>byt&#x16F;</em> (&#x10D;&#xED;sel od 0 do 255).\nZjednodu&#x161;en&#x11B; &#x159;e&#x10D;eno, mus&#xED;&#x161; je p&#x159;ev&#xE9;st na &#x159;et&#x11B;zec.</p>\n<p>Existuje spousta zp&#x16F;sob&#x16F;, jak zak&#xF3;dovat data do textu.\nKa&#x17E;d&#xFD; zp&#x16F;sob se sna&#x17E;&#xED; naj&#xED;t vhodnou rovnov&#xE1;hu mezi\n&#x10D;itelnost&#xED; pro lidi/po&#x10D;&#xED;ta&#x10D;e, d&#xE9;lkou z&#xE1;pisu,\nbezpe&#x10D;nost&#xED;, mo&#x17E;nostmi a roz&#x161;i&#x159;itelnost&#xED;.\nMy u&#x17E; zn&#xE1;me syntaxi Pythonu:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n    <span class=\"s1\">&apos;jm&#xE9;no&apos;</span><span class=\"p\">:</span> <span class=\"s1\">&apos;Anna&apos;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&apos;m&#x11B;sto&apos;</span><span class=\"p\">:</span> <span class=\"s1\">&apos;Brno&apos;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&apos;jazyky&apos;</span><span class=\"p\">:</span> <span class=\"p\">[</span><span class=\"s1\">&apos;&#x10D;e&#x161;tina&apos;</span><span class=\"p\">,</span> <span class=\"s1\">&apos;angli&#x10D;tina&apos;</span><span class=\"p\">,</span> <span class=\"s1\">&apos;Python&apos;</span><span class=\"p\">],</span>\n    <span class=\"s1\">&apos;v&#x11B;k&apos;</span><span class=\"p\">:</span> <span class=\"mi\">26</span><span class=\"p\">,</span>\n<span class=\"p\">}</span>\n</pre></div><p>Jin&#xFD; zp&#x16F;sob z&#xE1;pisu dat je <a href=\"http://www.yaml.org/\">YAML</a>:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"nt\">jm&#xE9;no</span><span class=\"p\">:</span> <span class=\"l l-Scalar l-Scalar-Plain\">Anna</span>\n<span class=\"nt\">m&#x11B;sto</span><span class=\"p\">:</span> <span class=\"l l-Scalar l-Scalar-Plain\">Brno</span>\n<span class=\"nt\">jazyky</span><span class=\"p\">:</span>\n  <span class=\"p p-Indicator\">-</span> <span class=\"l l-Scalar l-Scalar-Plain\">&#x10D;e&#x161;tina</span>\n  <span class=\"p p-Indicator\">-</span> <span class=\"l l-Scalar l-Scalar-Plain\">angli&#x10D;tina</span>\n  <span class=\"p p-Indicator\">-</span> <span class=\"l l-Scalar l-Scalar-Plain\">Python</span>\n<span class=\"nt\">v&#x11B;k</span><span class=\"p\">:</span> <span class=\"l l-Scalar l-Scalar-Plain\">26</span>\n</pre></div><p>Nebo t&#x159;eba <a href=\"http://en.wikipedia.org/wiki/Bencode\">Bencode</a>:</p>\n<div class=\"highlight\"><pre><code>d6:jazykyl9:&#x10D;e&#x161;tina11:angli&#x10D;tina6:Pythone4:v&#x11B;ki26e6:m&#x11B;sto4:Brno6:jm&#xE9;no4:Annae</code></pre></div><p>Existuj&#xED; i netextov&#xE9; form&#xE1;ty, jako\n<a href=\"https://docs.python.org/3/library/pickle.html\">Pickle 3</a>:</p>\n<div class=\"highlight\"><pre><code>}q(Xjm&#xC3;&#xA9;noqXAnnaqXm&#xC4;toqXBrnoqXjazykyq]q(X       &#xC4;e&#xC5;&#xA1;tinaqX\n                                                          angli&#xC4;tinaXPythonq       eXv&#xC4;q\nK&#x2592;u.</code></pre></div><p>A nakonec uvedu <a href=\"http://json.org/\">JSON</a>\n(z&#xA0;angl. <em>Javascript Object Notation</em> &#x201E;z&#xE1;pis Javascriptov&#xFD;ch objekt&#x16F;&#x201D;),\nkter&#xFD; se pro svou jednoduchost roz&#x161;&#xED;&#x159;il na Internetu nejv&#xED;c:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n  <span class=\"nt\">&quot;jm&#xE9;no&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;Anna&quot;</span><span class=\"p\">,</span>\n  <span class=\"nt\">&quot;m&#x11B;sto&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;Brno&quot;</span><span class=\"p\">,</span>\n  <span class=\"nt\">&quot;jazyky&quot;</span><span class=\"p\">:</span> <span class=\"p\">[</span><span class=\"s2\">&quot;&#x10D;e&#x161;tina&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;angli&#x10D;tina&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;Python&quot;</span><span class=\"p\">],</span>\n  <span class=\"nt\">&quot;v&#x11B;k&quot;</span><span class=\"p\">:</span> <span class=\"mi\">26</span>\n<span class=\"p\">}</span>\n</pre></div><div class=\"admonition note\"><p>Pozor na to, &#x17E;e a&#x10D;koli JSON vypad&#xE1; podobn&#x11B; jako z&#xE1;pis\nv&#xA0;Pythonu, je to jin&#xFD; form&#xE1;t s&#xA0;vlastn&#xED;mi pravidly.\nNezam&#x11B;&#x148;uj je!</p>\n<p>Aspo&#x148; ze za&#x10D;&#xE1;tku nedoporu&#x10D;uji JSON ps&#xE1;t ru&#x10D;n&#x11B;;\nnech na po&#x10D;&#xED;ta&#x10D;i, aby dal na spr&#xE1;vn&#xE9; m&#xED;sto spr&#xE1;vn&#xE9;\n&#x10D;&#xE1;rky a uvozovky.</p>\n</div><h2>JSON v Pythonu</h2>\n<p>K&#xF3;dov&#xE1;n&#xED; objekt&#x16F; v&#xA0;JSONu je jednoduch&#xE9;: existuje modul <code>json</code>,\njeho&#x17E; metoda <code>loads</code> na&#x10D;te data z &#x159;et&#x11B;zce:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"kn\">import</span> <span class=\"nn\">json</span>\n\n<span class=\"n\">json_retezec</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;&quot;&quot;</span>\n<span class=\"s2\">    {</span>\n<span class=\"s2\">      &quot;jm&#xE9;no&quot;: &quot;Anna&quot;,</span>\n<span class=\"s2\">      &quot;m&#x11B;sto&quot;: &quot;Brno&quot;,</span>\n<span class=\"s2\">      &quot;jazyky&quot;: [&quot;&#x10D;e&#x161;tina&quot;, &quot;angli&#x10D;tina&quot;, &quot;Python&quot;],</span>\n<span class=\"s2\">      &quot;v&#x11B;k&quot;: 26</span>\n<span class=\"s2\">    }</span>\n<span class=\"s2\">&quot;&quot;&quot;</span>\n\n<span class=\"n\">data</span> <span class=\"o\">=</span> <span class=\"n\">json</span><span class=\"o\">.</span><span class=\"n\">loads</span><span class=\"p\">(</span><span class=\"n\">json_retezec</span><span class=\"p\">)</span>\n<span class=\"k\">print</span><span class=\"p\">(</span><span class=\"n\">data</span><span class=\"p\">)</span>\n<span class=\"k\">print</span><span class=\"p\">(</span><span class=\"n\">data</span><span class=\"p\">[</span><span class=\"s1\">&apos;m&#x11B;sto&apos;</span><span class=\"p\">])</span>\n</pre></div><p>A pak tu je metoda <code>dumps</code>, kter&#xE1; naopak dan&#xE1; data zak&#xF3;duje\na vr&#xE1;t&#xED; &#x159;et&#x11B;zec:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"k\">print</span><span class=\"p\">(</span><span class=\"n\">json</span><span class=\"o\">.</span><span class=\"n\">dumps</span><span class=\"p\">(</span><span class=\"n\">data</span><span class=\"p\">))</span>\n<span class=\"go\">{&quot;v\\u011bk&quot;: 26, &quot;jm\\u00e9no&quot;: &quot;Anna&quot;, &quot;jazyky&quot;: [&quot;\\u010de\\u0161tina&quot;, &quot;angli\\u010dtina&quot;, &quot;Python&quot;], &quot;m\\u011bsto&quot;: &quot;Brno&quot;}</span>\n</pre></div><p>To, co vr&#xE1;t&#xED; jednoduch&#xE9; zavol&#xE1;n&#xED; <code>dumps(data)</code> je vhodn&#xE9; pro po&#x10D;&#xED;ta&#x10D;ov&#xE9;\nzpracov&#xE1;n&#xED;;\nm&#xE1;-li v&#xFD;sledn&#xE1; data &#x10D;&#xED;st &#x10D;lov&#x11B;k, nastav\n<code>ensure_ascii=False</code> (aby se p&#xED;smenka s&#xA0;diakritikou nek&#xF3;dovala pomoc&#xED; <code>\\</code>)\na <code>indent=2</code> (odsazen&#xED; dv&#x11B;ma mezerami).</p>\n<div class=\"highlight\"><pre><span></span><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"k\">print</span><span class=\"p\">(</span><span class=\"n\">json</span><span class=\"o\">.</span><span class=\"n\">dumps</span><span class=\"p\">(</span><span class=\"n\">data</span><span class=\"p\">,</span> <span class=\"n\">ensure_ascii</span><span class=\"o\">=</span><span class=\"bp\">False</span><span class=\"p\">,</span> <span class=\"n\">indent</span><span class=\"o\">=</span><span class=\"mi\">2</span><span class=\"p\">))</span>\n<span class=\"go\">{</span>\n<span class=\"go\">  &quot;v&#x11B;k&quot;: 26,</span>\n<span class=\"go\">  &quot;jm&#xE9;no&quot;: &quot;Anna&quot;,</span>\n<span class=\"go\">  &quot;jazyky&quot;: [</span>\n<span class=\"go\">    &quot;&#x10D;e&#x161;tina&quot;,</span>\n<span class=\"go\">    &quot;angli&#x10D;tina&quot;,</span>\n<span class=\"go\">    &quot;Python&quot;</span>\n<span class=\"go\">  ],</span>\n<span class=\"go\">  &quot;m&#x11B;sto&quot;: &quot;Brno&quot;</span>\n<span class=\"go\">}</span>\n</pre></div><p>Kompletn&#xED; popis modulu <code>json</code> &#x2013;\nv&#x10D;etn&#x11B; funkc&#xED; na z&#xE1;pis/&#x10D;ten&#xED; p&#x159;&#xED;mo do/ze soubor&#x16F; &#x2013;\nje v&#xA0;p&#x159;&#xED;slu&#x161;n&#xE9; <a href=\"https://docs.python.org/3/library/json.html\">dokumentaci</a>.</p>\n\n\n        "
    }
  }
}