Jak serializovat formulář Html do JSON

11.12.2023 Programování #html #json #serializace

Průvodce použitím serializace JSON jquery k serializaci dat formuláře a jejich odeslání


HTML formulář

JSON output

jquery.serializeJSON

Přidá metodu .serializeJSON() do jQuery (nebo Zepto ), která serializuje formulář do objektu JavaScriptu pomocí stejného formátu jako výchozí parametry požadavku Ruby on Rails.

Jak používat

Chcete-li použít serializeJSON, stáhněte si skript jquery.serializejson.js. A ujistěte se, že je zahrnut po jQuery, například:

<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="jquery.serializejson.js"></script>

Příklad použití

HTML formulář:

<form>
  <input type="text" name="title" value="Finding Loot"/>
  <input type="text" name="author[name]" value="John Smith"/>
  <input type="text" name="author[job]"  value="Legendary Pirate"/>
</form>

Javascript:

$('form').serializeJSON();
// returns =>
{
  title: "Finding Loot",
  author: {
    name: "John Smith",
    job: "Legendary Pirate"
  }
}

Je podporováno zadávání formulářů, textová oblast a značky výběru. Vnořené atributy a pole lze zadat pomocí attr[nested][nested] syntaxe.

HTML formulář:

<form id="my-profile">
  <!-- simple attribute -->
  <input type="text" name="fullName" value="Mario Izquierdo" />
  <!-- nested attributes -->
  <input type="text" name="address[city]"  value="San Francisco" />
  <input type="text" name="address[state][name]"  value="California" />
  <input type="text" name="address[state][abbr]"  value="CA" />
  <!-- array -->
  <input type="text" name="jobbies[]" value="code" />
  <input type="text" name="jobbies[]" value="climbing" />
  <!-- nested arrays, textareas, checkboxes ... -->
  <textarea name="projects[0][name]">serializeJSON</textarea>
  <textarea name="projects[0][language]">javascript</textarea>
  <input type="hidden"   name="projects[0][popular]" value="0" />
  <input type="checkbox" name="projects[0][popular]" value="1" checked />
  <textarea name="projects[1][name]">tinytest.js</textarea>
  <textarea name="projects[1][language]">javascript</textarea>
  <input type="hidden" name="projects[1][popular]" value="0" />
  <input type="checkbox" name="projects[1][popular]" value="1"/>
  <!-- select -->
  <select name="selectOne">
       <option value="paper">Paper</option>
       <option value="rock" selected>Rock</option>
       <option value="scissors">Scissors</option>
  </select>
  <!-- select multiple options, just name it as an array[] -->
  <select multiple name="selectMultiple[]">
       <option value="red"  selected>Red</option>
       <option value="blue" selected>Blue</option>
       <option value="yellow">Yellow</option>
  </select>
</form>

Javascript:

$('#my-profile').serializeJSON();
// returns =>
{
  fullName: "Mario Izquierdo",
  address: {
    city: "San Francisco",
    state: {
      name: "California",
      abbr: "CA"
    }
  },
  jobbies: ["code", "climbing"],
  projects: {
    '0': { name: "serializeJSON", language: "javascript", popular: "1" },
    '1': { name: "tinytest.js",   language: "javascript", popular: "0" }
  },
  selectOne: "rock",
  selectMultiple: ["red", "blue"]
}

Funkce serializeJSON vrací objekt JavaScript, nikoli řetězec JSON. Plugin měl být pravděpodobně nazýván serializeObject nebo podobně, ale tyto pluginy již existovaly.

Chcete-li převést na řetězec JSON, použijte JSON.stringify metodu, která je k dispozici ve všech hlavních nových prohlížečích. Pokud potřebujete podporovat velmi staré prohlížeče, stačí zahrnout polyfill json2.js (jak je popsáno na stackoverfow).

var obj = $('form').serializeJSON(); 
var jsonString = JSON.stringify(obj);

Implementace pluginu spoléhá na metodu .serializeArray() jQuery . To znamená, že pouze serializuje vstupy podporované .serializeArray(), což se řídí standardními pravidly W3C pro úspěšné ovládání . Zahrnuté prvky zejména nelze zakázat a musí obsahovat atribut name. Žádná hodnota tlačítka odeslání není serializována, protože formulář nebyl odeslán pomocí tlačítka. A data z prvků výběru souboru nejsou serializována.

Analyzujte hodnoty s typy

Všechny hodnoty atributů jsou ve výchozím nastavení řetězce. Ale můžete vynutit, aby byly hodnoty analyzovány s konkrétními typy připojením typu dvojtečkou.

<form>
  <input type="text" name="strbydefault" value=":string is the default (implicit) type"/>
  <input type="text" name="text:string" value=":string type can still be used to overrid other parsing options"/>
  <input type="text" name="excluded:skip" value="Use :skip to not include this field in the result"/>
  <input type="text" name="numbers[1]:number" value="1"/>
  <input type="text" name="numbers[1.1]:number" value="1.1"/>
  <input type="text" name="numbers[other stuff]:number" value="other stuff"/>
  <input type="text" name="bools[true]:boolean" value="true"/>
  <input type="text" name="bools[false]:boolean" value="false"/>
  <input type="text" name="bools[0]:boolean" value="0"/>
  <input type="text" name="nulls[null]:null" value="null"/>
  <input type="text" name="nulls[other stuff]:null" value="other stuff"/>
  <input type="text" name="autos[string]:auto" value="text with stuff"/>
  <input type="text" name="autos[0]:auto" value="0"/>
  <input type="text" name="autos[1]:auto" value="1"/>
  <input type="text" name="autos[true]:auto" value="true"/>
  <input type="text" name="autos[false]:auto" value="false"/>
  <input type="text" name="autos[null]:auto" value="null"/>
  <input type="text" name="autos[list]:auto" value="[1, 2, 3]"/>
  <input type="text" name="arrays[empty]:array" value="[]"/>
  <input type="text" name="arrays[list]:array" value="[1, 2, 3]"/>
  <input type="text" name="objects[empty]:object" value="{}"/>
  <input type="text" name="objects[dict]:object" value='{"my": "stuff"}'/>
</form>

$('form').serializeJSON();
// returns =>
{
  "strbydefault": ":string is the default (implicit) type",
  "text": ":string type can still be used to overrid other parsing options",
  // excluded:skip is not included in the output
  "numbers": {
    "1": 1,
    "1.1": 1.1,
    "other stuff": NaN, // <-- Not a Number
  },
  "bools": {
    "true": true,
    "false": false,
    "0": false, // <-- "false", "null", "undefined", "", "0" parse as false
  },
  "nulls": {
    "null": null, // <-- "false", "null", "undefined", "", "0" parse as null
    "other stuff": "other stuff"
  },
  "autos": { // <-- works like the parseAll option
    "string": "text with stuff",
    "0": 0, // <-- parsed as number
    "1": 1, // <-- parsed as number
    "true": true, // <-- parsed as boolean
    "false": false, // <-- parsed as boolean
    "null": null, // <-- parsed as null
    "list": "[1, 2, 3]" // <-- array and object types are not auto-parsed
  },
  "arrays": { // <-- uses JSON.parse
    "empty": [],
    "not empty": [1,2,3]
  },
  "objects": { // <-- uses JSON.parse
    "empty": {},
    "not empty": {"my": "stuff"}
  }
}

Typy lze také zadat pomocí atributu data-value-type, místo toho, abyste museli přidávat příponu „: type“:

<form>
  <input type="text" name="anumb" data-value-type="number" value="1"/>
  <input type="text" name="abool" data-value-type="boolean" value="true"/>
  <input type="text" name="anull" data-value-type="null" value="null"/>
  <input type="text" name="anauto" data-value-type="auto" value="0"/>
</form>

Možnosti

Ve výchozím nastavení .serializeJSON() bez možností má toto chování:

  • Hodnoty jsou vždy řetězce (pokud se k názvům vstupů nepřipojí :types)
  • Nezaškrtnutá políčka jsou ignorována (jak je definováno v pravidlech W3C pro úspěšné kontroly).
  • Zakázané prvky jsou ignorovány (pravidla W3C)
  • Klíče (názvy vstupů) jsou vždy řetězce (vnořené parametry jsou ve výchozím nastavení objekty)

Je to proto, že serializeJSON je navržen tak, aby se vrátil přesně stejně jako běžné odeslání formuláře HTML, když je serializován jako parametry Rack/Rails, což zajišťuje maximální kompatibilitu a stabilitu.

Povolené možnosti pro změnu výchozího chování:

  • checkboxUncheckedValue: řetězec, hodnota řetězce použitá u nezaškrtnutých políček (jinak jsou tyto hodnoty ignorovány). Například {checkboxUncheckedValue: ""}. Pokud je třeba hodnotu analyzovat (tj. na booleovskou nebo nulovou hodnotu), použijte volbu analýzy (např. parseBooleans: true) nebo definujte vstup pomocí typů :boolean nebo :null.
  • parseBooleans: true, automaticky detekuje a převádí řetězce "true" "false" na booleany true false.
  • parseNumbers: true, automaticky detekuje a převádí řetězce jako "1""33.33""-44" na čísla jako 133.33-44.
  • parseNulls: true, automaticky detekuje a převádí řetězec "null" na hodnotu null null.
  • parseAll: pravda, vše výše uvedené. To je stejné, jako kdyby výchozí :type byl :auto místo :string.
  • parseWithFunction: funkce, definujte vlastní parse function(inputValue, inputName) {return parsedValue}.
  • skipFalsyValuesForFields: [], přeskočit daná pole (podle názvu) s falešnými hodnotami. Můžete data-skip-falsy="true" také použít vstupní atribut. Falešné hodnoty jsou určeny po převodu na daný typ, všimněte si, že "0" jako :string je pravdivé, ale 0 jako :číslo je nepravdivé.
  • skipFalsyValuesForTypes: [], přeskočit daná pole (podle :type) s falešnými hodnotami (tj. skipFalsyValuesForTypes: ["string", "number"]přeskočit ""pro :string pole a 0 pole :number).
  • customTypes: {}, definujte své vlastní :types nebo přepište výchozí typy. Definováno jako objekt jako { type: function(value){...} }. Například: {customTypes: {nullable: function(str){ return str || null; }}.
  • defaultTypes: {defaultTypes} v případě, že chcete znovu definovat všechny :types. Definováno jako objekt jako { type: function(value){...} }
  • useIntKeysAsArrayIndex: true, při použití celých čísel jako klíčů (tj. < input name="foods[0]" value="banana" type="text" >), serializovat jako pole ( {"foods": ["banana"]}) místo objektu ( {"foods": {"0": "banana"}).

Další informace o použití možností v sekcích níže.

Zahrnout nezaškrtnutá políčka

Podle mého názoru je nejvíce matoucím detailem při serializaci formuláře zaškrtávací políčko typu vstupu, které bude obsahovat hodnotu, pokud je zaškrtnuto, a nic, pokud není zaškrtnuto.

Chcete-li se s tím vypořádat, je běžnou praxí použití skrytých polí pro „nezaškrtnuté“ hodnoty:

<!-- Only one booleanAttr will be serialized, being "true" or "false" depending if the checkbox is selected or not -->
<input type="hidden"   name="booleanAttr" value="false" />
<input type="checkbox" name="booleanAttr" value="true" />

Toto řešení je poněkud upovídané, ale je nenápadné a zajišťuje postupné vylepšování, protože jde o standardní chování HTML (funguje i bez JavaScriptu).

Ale pro usnadnění serializeJSON obsahuje možnost checkboxUncheckedValue a možnost přidat atribut data-unchecked-value do zaškrtávacích políček.

Například:

<form>
  <input type="checkbox" name="check1" value="true" checked/>
  <input type="checkbox" name="check2" value="true"/>
  <input type="checkbox" name="check3" value="true"/>
</form>

Ve výchozím nastavení se serializuje takto:

$('form').serializeJSON();
// returns =>
{'check1': 'true'} // Note that check2 and check3 are not included because they are not checked

Hodnotu „unchecked“ lze také zadat pomocí atributu HTML data-unchecked-value (Upozorňujeme, že tento atribut rozpozná pouze plugin):

<form id="checkboxes">
  <input type="checkbox" name="checked[bool]" value="true" data-unchecked-value="false" checked/>
  <input type="checkbox" name="checked[bin]" value="1" data-unchecked-value="0" checked/>
  <input type="checkbox" name="checked[cool]" value="YUP" checked/>
  <input type="checkbox" name="unchecked[bool]" value="true" data-unchecked-value="false" />
  <input type="checkbox" name="unchecked[bin]" value="1" data-unchecked-value="0" />
  <input type="checkbox" name="unchecked[cool]" value="YUP" /> <!-- No unchecked value specified -->
</form>

Ve výchozím nastavení se serializuje takto:

$('form#checkboxes').serializeJSON(); // Note no option is used
// returns =>
{
  'checked': {
    'bool':  'true',
    'bin':   '1',
    'cool':  'YUP'
  },
  'unchecked': {
    'bool': 'false',
    'bin':  '0'
    // Note that unchecked cool does not appear, because it doesn't use data-unchecked-value
  }
}

checkboxUncheckedValue Možnost i atribut můžete použít data-unchecked-value současně, v takovém případě má atribut přednost před možností. A pamatujte, že jej můžete zkombinovat s dalšími možnostmi pro analýzu hodnot.

$('form#checkboxes').serializeJSON({checkboxUncheckedValue: 'NOPE', parseBooleans: true, parseNumbers: true});
// returns =>
{
  'checked': {
    'bool': true,
    'bin': 1,
    'cool': 'YUP'
  },
  'unchecked': {
    'bool': false, // value from data-unchecked-value attribute, and parsed with parseBooleans
    'bin': 0,     // value from data-unchecked-value attribute, and parsed with parseNumbers
    'cool': 'NOPE' // value from checkboxUncheckedValue option
  }
}

Automaticky zjišťovat typy pomocí možností analýzy

Výchozí typ je :string, takže všechny hodnoty jsou ve výchozím nastavení Strings, i když vypadají jako logické hodnoty, čísla nebo hodnoty null. Například:

<form>
  <input type="text" name="bool[true]" value="true"/>
  <input type="text" name="bool[false]" value="false"/>
  <input type="text" name="number[0]" value="0"/>
  <input type="text" name="number[1]" value="1"/>
  <input type="text" name="number[2.2]" value="2.2"/>
  <input type="text" name="number[-2.25]" value="-2.25"/>
  <input type="text" name="null" value="null"/>
  <input type="text" name="string" value="text is always string"/>
  <input type="text" name="empty" value=""/>
</form>

$('form').serializeJSON();
// returns =>
{
  "bool": {
    "true": "true",
    "false": "false",
  }
  "number": {
    "0": "0",
    "1": "1",
    "2.2": "2.2",
    "-2.25": "-2.25",
  }
  "null": "null",
  "string": "text is always string",
  "empty": ""
}

Všimněte si, že všechny hodnoty jsou řetězce.

K automatické detekci typů můžete použít typ :auto (přidat :auto k názvu vstupu). Nebo můžete použít možnosti analýzy. Chcete-li například analyzovat hodnoty null a čísla:

$('form').serializeJSON({parseNulls: true, parseNumbers: true});
// returns =>
{
  "bool": {
    "true": "true", // booleans are still strings, because parseBooleans was not set
    "false": "false",
  }
  "number": {
    "0": 0, // numbers are parsed because parseNumbers: true
    "1": 1,
    "2.2": 2.2,
    "-2.25": -2.25,
  }
  "null": null, // "null" strings are converted to null becase parseNulls: true
  "string": "text is always string",
  "empty": ""
}

Ve vzácných případech lze vlastní analyzátor definovat pomocí funkce:

var emptyStringsAndZerosToNulls = function(val, inputName) {
  if (val === "") return null; // parse empty strings as nulls
  if (val === 0)  return null; // parse 0 as null
  return val;
}
$('form').serializeJSON({parseWithFunction: emptyStringsAndZerosToNulls, parseNumbers: true});
// returns =>
{
  "bool": {
    "true": "true",
    "false": "false",
  }
  "number": {
    "0": null, // <-- parsed with custom function
    "1": 1,
    "2.2": 2.2,
    "-2.25": -2.25,
  }
  "null": "null",
  "string": "text is always string",
  "empty": null // <-- parsed with custom function
}

Vlastní typy

Pomocí této možnosti můžete definovat své vlastní typy nebo přepsat výchozí hodnoty customTypes. Například:

<form>
  <input type="text" name="scary:alwaysBoo" value="not boo"/>
  <input type="text" name="str:string" value="str"/>
  <input type="text" name="number:number" value="5"/>
</form>

$('form').serializeJSON({
  customTypes: {
    alwaysBoo: function(str) { // value is always a string
      return "boo";
    },
    string: function(str) { // all strings will now end with " override"
      return str + " override";
    }
  }
});
// returns =>
{
  "scary": "boo", // <-- parsed with type :alwaysBoo
  "str": "str override", // <-- parsed with new type :string (instead of the default)
  "number": 5, // <-- the default :number still works
}

Výchozí typy jsou definovány v $.serializeJSON.defaultOptions.defaultTypes. Pokud chcete definovat vlastní sadu typů, můžete také tuto možnost předefinovat (nepřepíše typy, ale definuje novou sadu typů).

Ignorujte prázdná pole formuláře

Můžete použít volbu .serializeJSON(skipFalsyValuesForTypes: ["string"]), která ignoruje jakékoli pole řetězce s prázdnou hodnotou (výchozí typ je :string a prázdné řetězce jsou falešné).

Další možností, protože serializeJSON() je volána na objektu jQuery, je pouze použít správný selektor jQuery k přeskočení prázdných hodnot ( další informace viz problém #28 ):

// Select only imputs that have a non-empty value
$('form :input[value!=""]').serializeJSON();
// Or filter them from the form
obj = $('form').find('input').not('[value=""]').serializeJSON();
// For more complicated filtering, you can use a function
obj = $form.find(':input').filter(function () {
          return $.trim(this.value).length > 0
      }).serializeJSON();

Ignorujte pole s falešnými hodnotami

Při použití :types můžete také přeskočit falešné hodnoty ( false, "", 0, null, undefined, NaN) pomocí volby skipFalsyValuesForFields: ["fullName", "address[city]"] nebo skipFalsyValuesForTypes: ["string", "null"].

Nebo nastavení datového atributu data-skip-falsy="true"na vstupech, které by měly být ignorovány. Všimněte si, že data-skip-falsy zná pole :types, takže ví, jak přeskočit neprázdný vstup, jako je tento  (Všimněte si, "0" že řetězec není nepravdivý, ale 0 číslo je nepravdivý)).

Použijte celočíselné klíče jako indexy pole

Ve výchozím nastavení jsou všechny serializované klíče řetězce, včetně klíčů, které vypadají jako čísla takto:

<form>
  <input type="text" name="arr[0]" value="foo"/>
  <input type="text" name="arr[1]" value="var"/>
  <input type="text" name="arr[5]" value="inn"/>
</form>

$('form').serializeJSON();
// arr is an object =>
{'arr': {'0': 'foo', '1': 'var', '5': 'inn' }}

Jak se chová Rack parse_nested_query. Pamatujte, že formát vstupního názvu serializeJSON je plně kompatibilní s parametry Rails, které jsou analyzovány pomocí této metody Rack.

Použijte možnost useIntKeysAsArrayIndex interpretovat celá čísla jako indexy pole:

$('form').serializeJSON({useIntKeysAsArrayIndex: true});
// arr is an array =>
{'arr': ['foo', 'var', undefined, undefined, undefined, 'inn']}

Poznámka: Toto bylo výchozí chování serializeJSON před verzí 2. Tuto možnost můžete použít pro zpětnou kompatibilitu.

Výchozí

Všechny výchozí hodnoty možností jsou definovány v $.serializeJSON.defaultOptions. Můžete jej pouze upravit, abyste se vyhnuli nastavení možnosti při každém volání na serializeJSON.

Například:

$.serializeJSON.defaultOptions.parseAll = true; // parse booleans, numbers and nulls by default
$('form').serializeJSON(); // No options => then use $.serializeJSON.defaultOptions
// returns =>
{
  "bool": {
    "true": true,
    "false": false,
  }
  "number": {
    "0": 0,
    "1": 1,
    "2.2": 2.2,
    "-2.25": -2.25,
  }
  "null": null,
  "string": "text is always string",
  "empty": ""
}