JQuery: 提交表单数据,转换表单数据为json,values of Form to Json (jquery.serializeJSON)

项目:https://github.com/marioizquierdo/jquery.serializeJSON

下载:jquery.serializeJSON-master

jquery.serializeJSON

前端在处理含有大量数据提交的表单时,除了使用Form直接提交刷新页面之外,经常碰到的需求是收集表单信息成数据对象,Ajax提交。

而在处理复杂的表单时,需要一个一个区手动判断处理字段值,显得非常麻烦。接下来介绍的插件将解决这个问题。

使用jquery.serializeJSON,可以在基于jQuery或者Zepto的页面中,调用 .serializeJSON() 方法来序列化form表单的数据成JS对象。

安装

Install with bower bower install jquery.serializeJSON, or npm npm install jquery-serializejson, or just download the jquery.serializejson.js script.

下载:https://github.com/marioizquierdo/jquery.serializeJSON

只需要在jQuery或者Zepto时候引入即可

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

用法

HTML form (input, textarea and select tags supported):

<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" />

  <!-- 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"]
}

The serializeJSON function returns a JavaScript object, not a JSON String. It should probably have been called serializeObject, or something like that, but those names were already taken.

To serialize into JSON, use the JSON.stringify method, that is available on all major new browsers. To support old browsers, just include the json2.js polyfill (as described on stackoverfow).

serializeJSON方法返回一个JS对象,并非JSON字符串。可以使用 JSON.stringify 转换成字符串(注意IE8兼容性)。

  var jsonString = JSON.stringify(obj);

Note that .serializeJSON() implememtation relies on jQuery’s .serializeArray() to grab the form attributes and then create the object using the names. That means, it will serialize the inputs that are supported by .serializeArray(), that uses the standard W3C rules for successful controls to determine which elements it should include. In particular, the included elements cannot be disabled and must contain a name attribute. No submit button value is serialized since the form was not submitted using a button. And data from file select elements is not serialized.

指定数据类型 Parse values with :types

获取到的属性值一般是字符串,可以通过HTML指定类型 : type 进行强制转换。

<form>
  <input type="text" name="deftype"          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 =>
{
  "deftype": "default type is :string",
  "text": ":string type overrides parsing options",
  // excluded:skip is not included in the output
  "numbers": {
    "1": 1,
    "1.1": 1.1,
    "other stuff": NaN, // <-- Other stuff parses as 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 as 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": { // <-- works using JSON.parse
    "empty": [],
    "not empty": [1,2,3]
  },
  "objects": { // <-- works using JSON.parse
    "empty": {},
    "not empty": {"my": "stuff"}
  }
}

数据类型也可以指定在 data-value-type 属性中,代替 :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>

Options配置

默认配置

  • Values始终为字符串(除非在input names使用:types )
  • Keys始终为字符串(默认不自动检测是否需要转换为数组)
  • 未选择的checkboxes会被忽略
  • disabledelements会被忽略

自定义配置

写法 释义
checkboxUncheckedValue: string 针对未勾选的checkboxes,设定值
parseBooleans: true 自动检测转换”true”、”false”为布尔值true、false
parseNumbers: true 自动检测转换”1″、”33.33″、”-44″为数字1、33.33、-44
parseNulls: true 自动检测字符串”null”为null
parseAll: true 自动检测转换以上类型的字符串
parseWithFunction: function 自定义转换函数 function(value, name){return parsedValue}
customTypes: {} 自定义:types覆盖默认types,如{type: function(value){…}}
defaultTypes: {defaultTypes} 重新定义所有的:types,如{type: function(value){…}}
useIntKeysAsArrayIndex: true 当keys为整数时,将序列化为数组

For convenience, you can change the default behavior with:

  • checkboxUncheckedValue: string, Use this value for unchecked checkboxes, instead of ignoring them. Make sure to use a String. If the value needs to be parsed (i.e. to a Boolean) use a parse option (i.e. parseBooleans: true).
  • parseBooleans: true, automatically detect and convert strings "true" and "false" to booleans true and false.
  • parseNumbers: true, automatically detect and convert strings like "1", "33.33", "-44" to numbers like 1, 33.33, -44.
  • parseNulls: true, automatically detect and convert the string "null" to the null value null.
  • parseAll: true, all of the above. This is the same as if the default :type was :auto instead of :string.
  • parseWithFunction: function, define your own parse function(inputValue, inputName) { return parsedValue }
  • skipFalsyValuesForFields: [], skip fields with given names and falsy values. You can use data-skip-falsy="true" input attribute as well. Falsy values are determined after converting to a given type, note that "0" as :string is truthy, but 0 as :number is falsy.
  • skipFalsyValuesForTypes: [], skip fields with given types and falsy values (i.e. skipFalsyValuesForTypes: ["string", "number"] would skip "" for :string fields, and 0 for :number fields).
  • customTypes: {}, define your own :types or override the default types. Defined as an object like { type: function(value){...} }
  • defaultTypes: {defaultTypes}, in case you want to re-define all the :types. Defined as an object like { type: function(value){...} }
  • useIntKeysAsArrayIndex: true, when using integers as keys (i.e. <input name="foods[0]" value="banana">), serialize as an array ({"foods": ["banana"]}) instead of an object ({"foods": {"0": "banana"}).

More info about options usage in the sections below.

包含未勾选的checkboxes

serializeJSON 支持 checkboxUncheckedValue 配置,或者可以在checkboxes添加 data-unchecked-value 属性。

<!-- 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" />

This solution is somehow verbose, but it is unobtrusive and ensures progressive enhancement, because it is the standard HTML behavior (also works without JavaScript).

But, to make things easier, serializeJSON includes the option checkboxUncheckedValue and the possibility to add the attribute data-unchecked-value to the checkboxes.

For example:

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

默认方法:

$('form').serializeJSON();

// returns =>
{'check1': 'true'} // Note that check2 and check3 are not included because they are not checked

上面的写法会忽略未勾选的复选框。如果需要包含,则可以使用以下方法:

1. 配置checkboxUncheckedValue

$('form').serializeJSON({checkboxUncheckedValue: "false"});

// returns =>
{'check1': 'true', check2: 'false', check3: 'false'}

2. 添加data-unchecked-value属性

<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>

Serializes like this by default:

$('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
  }
}

You can use both the option checkboxUncheckedValue and the attribute data-unchecked-value at the same time, in which case the attribute has precedence over the option. And remember that you can combine it with other options to parse values as well.

$('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
  }
}

自动检测转换类型

默认的类型为字符串 :string ,可以通过配置转换为其它类型

$('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": ""
}

在极少数情况下,可以使用自定义转换函数

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
}

自定义类型

可以使用 customTypes 配置自定义类型或者覆盖默认类型($.serializeJSON.defaultOptions.defaultTypes

<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>

JS

$('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
}

忽略空表单字段

 

更多参考:jquery.serializeJSON: 包含未勾选的checkboxes, Problem with checkbox checked,

 

本文:JQuery: 提交表单数据,转换表单数据为json,values of Form to Json (jquery.serializeJSON)