公司不是你家,领导不是你妈。本文已被 https://www.yourbatman.cn 收录,里面一并有Spring技术栈、MyBatis、JVM、中间件等小而美的专栏供以免费学习。关注公众号【BAT的乌托邦】逐个击破,深入掌握,拒绝浅尝辄止。

前言

各位好,我是A哥(YourBatman)。上篇文章:3. 懂了这些,方敢在简历上说会用Jackson写JSON 聊完,流式API的写部分可以认为你已完全掌握了,本文了解它读的部分。

版本约定

  • Jackson版本:2.11.0
  • Spring Framework版本:5.2.6.RELEASE
  • Spring Boot版本:2.3.0.RELEASE

小贴士:截止到本文,本系列前面所有示例都只仅仅导入jackson-core而已,后续若要新增jar包我会额外说明,否则相同

正文

什么叫读JSON?就是把一个JSON 字符串 解析为对象or树模型嘛,因此也称作解析JSON串。Jackson底层流式API使用JsonParser来完成JSON字符串的解析。

最简使用Demo

准备一个POJO:

@Data
public class Person {
private String name;
private Integer age;
}

测试用例:把一个JSON字符串绑定(封装)进一个POJO对象里

@Test
public void test1() throws IOException {
String jsonStr = "{\"name\":\"YourBatman\",\"age\":18}";
Person person = new Person(); JsonFactory factory = new JsonFactory();
try (JsonParser jsonParser = factory.createParser(jsonStr)) { // 只要还没结束"}",就一直读
while (jsonParser.nextToken() != JsonToken.END_OBJECT) {
String fieldname = jsonParser.getCurrentName();
if ("name".equals(fieldname)) {
jsonParser.nextToken();
person.setName(jsonParser.getText());
} else if ("age".equals(fieldname)) {
jsonParser.nextToken();
person.setAge(jsonParser.getIntValue());
}
} System.out.println(person);
}
}

运行程序,输出:

Person(name=YourBatman, age=18)

成功把一个JSON字符串的值解析到Person对象。你可能会疑问,怎么这么麻烦?那当然,这是底层流式API,纯手动档嘛。你获得了性能,可不要失去一些便捷性嘛。

小贴士:底层流式API一般面向“专业人士”,应用级开发使用高阶API ObjectMapper即可。当然,读完本系列就能让你完全具备“专业人士”的实力

JsonParser针对不同的value类型,提供了非常多的方法用于实际值的获取。

直接值获取:

// 获取字符串类型
public abstract String getText() throws IOException; // 数字Number类型值 标量值(支持的Number类型参照NumberType枚举)
public abstract Number getNumberValue() throws IOException;
public enum NumberType {
INT, LONG, BIG_INTEGER, FLOAT, DOUBLE, BIG_DECIMAL
}; public abstract int getIntValue() throws IOException;
public abstract long getLongValue() throws IOException;
...
public abstract byte[] getBinaryValue(Base64Variant bv) throws IOException;

这类方法可能会抛出异常:比如value值本不是数字但你调用了getInValue()方法~

小贴士:如果value值是null,像getIntValue()、getBooleanValue()等这种直接获取方法是会抛出异常的,但getText()不会

带默认值的值获取,具有更好安全性:

public String getValueAsString() throws IOException {
return getValueAsString(null);
}
public abstract String getValueAsString(String def) throws IOException;
...
public long getValueAsLong() throws IOException {
return getValueAsLong(0);
}
public abstract long getValueAsLong(long def) throws IOException;
...

此类方法若碰到数据的转换失败时,不会抛出异常,把def作为默认值返回。

组合方法

JsonGenerator一样,JsonParser也提供了高钙片组合方法,让你更加便捷的使用。

自动绑定

听起来像高级功能,是的,它必须依赖于ObjectCodec去实现,因为实际是全部委托给了它去完成的,也就是我们最为熟悉的readXXX系列方法:



我们知道,ObjectMapper就是一个ObjectCodec,它属于高级API,本文显然不会用到ObjectMapper它喽,因此我们自己手敲一个实现来完成此功能。

自定义一个ObjectCodec,Person类专用:用于把JSON串自动绑定到实例属性。

public class PersonObjectCodec extends ObjectCodec {
...
@SneakyThrows
@Override
public <T> T readValue(JsonParser jsonParser, Class<T> valueType) throws IOException {
Person person = (Person) valueType.newInstance(); // 只要还没结束"}",就一直读
while (jsonParser.nextToken() != JsonToken.END_OBJECT) {
String fieldname = jsonParser.getCurrentName();
if ("name".equals(fieldname)) {
jsonParser.nextToken();
person.setName(jsonParser.getText());
} else if ("age".equals(fieldname)) {
jsonParser.nextToken();
person.setAge(jsonParser.getIntValue());
}
} return (T) person;
}
...
}

有了它,就可以实现我们的自动绑定了,书写测试用例:

@Test
public void test3() throws IOException {
String jsonStr = "{\"name\":\"YourBatman\",\"age\":18, \"pickName\":null}"; JsonFactory factory = new JsonFactory();
try (JsonParser jsonParser = factory.createParser(jsonStr)) {
jsonParser.setCodec(new PersonObjectCodec()); System.out.println(jsonParser.readValueAs(Person.class));
}
}

运行程序,输出:

Person(name=YourBatman, age=18)

这就是ObjectMapper自动绑定的核心原理所在,其它更为强大能力将在后续章节详细展开。

JsonToken

在上例解析过程中,有一个非常重要的角色,那便是:JsonToken。它表示解析JSON内容时,用于返回结果的基本标记类型的枚举。

public enum JsonToken {
NOT_AVAILABLE(null, JsonTokenId.ID_NOT_AVAILABLE), START_OBJECT("{", JsonTokenId.ID_START_OBJECT),
END_OBJECT("}", JsonTokenId.ID_END_OBJECT),
START_ARRAY("[", JsonTokenId.ID_START_ARRAY),
END_ARRAY("]", JsonTokenId.ID_END_ARRAY), // 属性名(key)
FIELD_NAME(null, JsonTokenId.ID_FIELD_NAME), // 值(value)
VALUE_EMBEDDED_OBJECT(null, JsonTokenId.ID_EMBEDDED_OBJECT),
VALUE_STRING(null, JsonTokenId.ID_STRING),
VALUE_NUMBER_INT(null, JsonTokenId.ID_NUMBER_INT),
VALUE_NUMBER_FLOAT(null, JsonTokenId.ID_NUMBER_FLOAT),
VALUE_TRUE("true", JsonTokenId.ID_TRUE),
VALUE_FALSE("false", JsonTokenId.ID_FALSE),
VALUE_NULL("null", JsonTokenId.ID_NULL),
}

为了辅助理解,A哥用一个例子,输出各个部分一目了然:

@Test
public void test2() throws IOException {
String jsonStr = "{\"name\":\"YourBatman\",\"age\":18, \"pickName\":null}";
System.out.println(jsonStr);
JsonFactory factory = new JsonFactory();
try (JsonParser jsonParser = factory.createParser(jsonStr)) { while (true) {
JsonToken token = jsonParser.nextToken();
System.out.println(token + " -> 值为:" + jsonParser.getValueAsString()); if (token == JsonToken.END_OBJECT) {
break;
}
}
}
}

运行程序,输出:

{"name":"YourBatman","age":18, "pickName":null}
START_OBJECT -> 值为:null FIELD_NAME -> 值为:name
VALUE_STRING -> 值为:YourBatman FIELD_NAME -> 值为:age
VALUE_NUMBER_INT -> 值为:18 FIELD_NAME -> 值为:pickName
VALUE_NULL -> 值为:null END_OBJECT -> 值为:null

从左至右解析,一一对应。各个部分用下面这张图可以简略表示出来:

小贴士:解析时请确保你的的JSON串是合法的,否则抛出JsonParseException异常

JsonParser的Feature

它是JsonParser的一个内部枚举类,共15个枚举值:

public enum Feature {
AUTO_CLOSE_SOURCE(true), ALLOW_COMMENTS(false),
ALLOW_YAML_COMMENTS(false),
ALLOW_UNQUOTED_FIELD_NAMES(false),
ALLOW_SINGLE_QUOTES(false),
@Deprecated
ALLOW_UNQUOTED_CONTROL_CHARS(false),
@Deprecated
ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER(false),
@Deprecated
ALLOW_NUMERIC_LEADING_ZEROS(false),
@Deprecated
ALLOW_LEADING_DECIMAL_POINT_FOR_NUMBERS(false),
@Deprecated
ALLOW_NON_NUMERIC_NUMBERS(false),
@Deprecated
ALLOW_MISSING_VALUES(false),
@Deprecated
ALLOW_TRAILING_COMMA(false), STRICT_DUPLICATE_DETECTION(false),
IGNORE_UNDEFINED(false),
INCLUDE_SOURCE_IN_LOCATION(true);
}

小贴士:枚举值均为bool类型,括号内为默认值

每个枚举值都控制着JsonParser不同的行为。下面分类进行解释

底层I/O流相关

自2.10版本后,使用StreamReadFeature#AUTO_CLOSE_SOURCE代替

Jackson的流式API指的是I/O流,所以即使是,底层也是用I/O流(Reader)去读取然后解析的。

AUTO_CLOSE_SOURCE(true)

原理和JsonGenerator的AUTO_CLOSE_TARGET(true)一样,不再解释,详见上篇文章对应部分。

支持非标准格式

JSON是有规范的,在它的规范里并没有描述到对注释的规定、对控制字符的处理等等,也就是说这些均属于非标准行为。比如这个JSON串:

{
"name" : "YourBarman", // 名字
"age" : 18 // 年龄
}

你看,若你这么写IDEA都会飘红提示你:



但是,在很多使用场景(特别是JavaScript)里,我们会在JSON串里写注释(属性多时尤甚)那么对于这种串,JsonParser如何控制处理呢?它提供了对非标准JSON格式的兼容,通过下面这些特征值来控制。

ALLOW_COMMENTS(false)

自2.10版本后,使用JsonReadFeature#ALLOW_JAVA_COMMENTS代替

是否允许/* */或者//这种类型的注释出现。

@Test
public void test4() throws IOException {
String jsonStr = "{\n" +
"\t\"name\" : \"YourBarman\", // 名字\n" +
"\t\"age\" : 18 // 年龄\n" +
"}"; JsonFactory factory = new JsonFactory();
try (JsonParser jsonParser = factory.createParser(jsonStr)) {
// 开启注释支持
// jsonParser.enable(JsonParser.Feature.ALLOW_COMMENTS); while (jsonParser.nextToken() != JsonToken.END_OBJECT) {
String fieldname = jsonParser.getCurrentName();
if ("name".equals(fieldname)) {
jsonParser.nextToken();
System.out.println(jsonParser.getText());
} else if ("age".equals(fieldname)) {
jsonParser.nextToken();
System.out.println(jsonParser.getIntValue());
}
}
}
}

运行程序,抛出异常:

com.fasterxml.jackson.core.JsonParseException: Unexpected character ('/' (code 47)): maybe a (non-standard) comment? (not recognized as one since Feature 'ALLOW_COMMENTS' not enabled for parser)
at [Source: (String)"{
"name" : "YourBarman", // 名字
"age" : 18 // 年龄
}"; line: 2, column: 26]

放开注释的代码,再次运行程序,正常work

ALLOW_YAML_COMMENTS(false)

自2.10版本后,使用JsonReadFeature#ALLOW_YAML_COMMENTS代替

顾名思义,开启后将支持Yaml格式的的注释,也就是#形式的注释语法。

ALLOW_UNQUOTED_FIELD_NAMES(false)

自2.10版本后,使用JsonReadFeature#ALLOW_UNQUOTED_FIELD_NAMES代替

是否允许属性名不带双引号"",比较简单,示例略。

ALLOW_SINGLE_QUOTES(false)

自2.10版本后,使用JsonReadFeature#ALLOW_SINGLE_QUOTES代替

是否允许属性名支持单引号,也就是使用''包裹,形如这样:

{
'age' : 18
}

ALLOW_UNQUOTED_CONTROL_CHARS(false)

自2.10版本后,使用JsonReadFeature#ALLOW_UNESCAPED_CONTROL_CHARS代替

是否允许JSON字符串包含非引号控制字符(值小于32的ASCII字符,包含制表符和换行符)。 由于JSON规范要求对所有控制字符使用引号,这是一个非标准的特性,因此默认禁用。

那么,哪些字符属于控制字符呢?做个简单科普:我们一般说的ASCII码共128个字符(7bit),共分为两大类

控制字符

控制字符,也叫不可打印字符。第0~32号及第127号(共34个)是控制字符,例如常见的:LF(换行)CR(回车)、FF(换页)、DEL(删除)、BS(退格)等都属于此类。

控制字符大部分已经废弃不用了,它们的用途主要是用来操控已经处理过的文字,ASCII值为8、9、10 和13 分别转换为退格、制表、换行和回车字符。它们并没有特定的图形显示,但会依不同的应用程序,而对文本显示有不同的影响。

话外音:你看不见我,但我对你影响还蛮大

非控制字符

也叫可显示字符,或者可打印字符,能从键盘直接输入的字符。比如0-9数字,逗号、分号这些等等。

话外音:你肉眼能看到的字符就属于非控制字符

ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER(false)

自2.10版本后,使用JsonReadFeature#ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER代替

是否允许**反斜杠**转义任何字符。这句话不是非常好理解,看下面这个例子:

@Test
public void test4() throws IOException {
String jsonStr = "{\"name\" : \"YourB\\'atman\" }"; JsonFactory factory = new JsonFactory();
try (JsonParser jsonParser = factory.createParser(jsonStr)) {
// jsonParser.enable(JsonParser.Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER); while (jsonParser.nextToken() != JsonToken.END_OBJECT) {
String fieldname = jsonParser.getCurrentName();
if ("name".equals(fieldname)) {
jsonParser.nextToken();
System.out.println(jsonParser.getText());
}
}
}
}

运行程序,报错:

com.fasterxml.jackson.core.JsonParseException: Unrecognized character escape ''' (code 39)
at [Source: (String)"{"name" : "YourB\'atman" }"; line: 1, column: 19]
...

放开注释掉的代码,再次运行程序,一切正常,输出:YourB'atman

ALLOW_NUMERIC_LEADING_ZEROS(false)

自2.10版本后,使用JsonReadFeature#ALLOW_LEADING_ZEROS_FOR_NUMBERS代替

是否允许像00001这样的“数字”出现(而不报错)。看例子:

@Test
public void test5() throws IOException {
String jsonStr = "{\"age\" : 00018 }"; JsonFactory factory = new JsonFactory();
try (JsonParser jsonParser = factory.createParser(jsonStr)) {
// jsonParser.enable(JsonParser.Feature.ALLOW_NUMERIC_LEADING_ZEROS); while (jsonParser.nextToken() != JsonToken.END_OBJECT) {
String fieldname = jsonParser.getCurrentName();
if ("age".equals(fieldname)) {
jsonParser.nextToken();
System.out.println(jsonParser.getIntValue());
}
}
}
}

运行程序,输出:

com.fasterxml.jackson.core.JsonParseException: Invalid numeric value: Leading zeroes not allowed
at [Source: (String)"{"age" : 00018 }"; line: 1, column: 11]
...

放开注掉的代码,再次运行程序,一切正常。输出18

ALLOW_LEADING_DECIMAL_POINT_FOR_NUMBERS(false)

自2.10版本后,使用JsonReadFeature#ALLOW_LEADING_DECIMAL_POINT_FOR_NUMBERS代替

是否允许小数点.打头,也就是说.1这种小数格式是否合法。默认是不合法的,需要开启此特征才能支持,例子就略了,基本同上。

ALLOW_NON_NUMERIC_NUMBERS(false)

自2.10版本后,使用JsonReadFeature#ALLOW_NON_NUMERIC_NUMBERS代替

是否允许一些解析器识别一组“非数字”(如NaN)作为合法的浮点数值。这个属性和上篇文章的JsonGenerator#QUOTE_NON_NUMERIC_NUMBERS特征值是遥相呼应的。

@Test
public void test5() throws IOException {
String jsonStr = "{\"percent\" : NaN }"; JsonFactory factory = new JsonFactory();
try (JsonParser jsonParser = factory.createParser(jsonStr)) {
// jsonParser.enable(JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS); while (jsonParser.nextToken() != JsonToken.END_OBJECT) {
String fieldname = jsonParser.getCurrentName();
if ("percent".equals(fieldname)) {
jsonParser.nextToken();
System.out.println(jsonParser.getFloatValue());
}
}
}
}

运行程序,抛错:

com.fasterxml.jackson.core.JsonParseException: Non-standard token 'NaN': enable JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS to allow
at [Source: (String)"{"percent" : NaN }"; line: 1, column: 17]

放开注释掉的代码,再次运行,一切正常。输出:

NaN

小贴士:NaN也可以表示一个Float对象,是的你没听错,即使它不是数字但它也是Float类型。具体你可以看看Float源码里的那几个常量

ALLOW_MISSING_VALUES(false)

自2.10版本后,使用JsonReadFeature#ALLOW_MISSING_VALUES代替

是否允许支持JSON数组中“缺失”值。怎么理解:数组中缺失了值表示两个逗号之间,啥都没有,形如这样[value1, , value3]

@Test
public void test6() throws IOException {
String jsonStr = "{\"names\" : [\"YourBatman\",,\"A哥\",,] }"; JsonFactory factory = new JsonFactory();
try (JsonParser jsonParser = factory.createParser(jsonStr)) {
// jsonParser.enable(JsonParser.Feature.ALLOW_MISSING_VALUES); while (jsonParser.nextToken() != JsonToken.END_OBJECT) {
String fieldname = jsonParser.getCurrentName();
if ("names".equals(fieldname)) {
jsonParser.nextToken(); while (jsonParser.nextToken() != JsonToken.END_ARRAY) {
System.out.println(jsonParser.getText());
}
}
}
}
}

运行程序,抛错:

YourBatman // 能输出一个,毕竟第一个part(JsonToken)是正常的嘛

com.fasterxml.jackson.core.JsonParseException: Unexpected character (',' (code 44)): expected a valid value (JSON String, Number, Array, Object or token 'null', 'true' or 'false')
at [Source: (String)"{"names" : ["YourBatman",,"A哥",,] }"; line: 1, column: 27]

放开注释掉的代码,再次运行,一切正常,结果为:

YourBatman
null
A哥
null
null

请注意:此时数组的长度是5哦。

小贴士:此处用的String类型展示结果,是因为null可以作为String类型(jsonParser.getText()得到null是合法的)。但如果你使用的int类型(或者bool类型),那么如果是null的话就报错喽Current token (VALUE_NULL) not of boolean type,有兴趣的亲可自行尝试,巩固下理解的效果。报错原因文上已有说明~

ALLOW_TRAILING_COMMA(false)

自2.10版本后,使用JsonReadFeature#ALLOW_TRAILING_COMMA代替

是否允许最后一个多余的逗号(一定是最后一个)。这个特征是非常重要的,若开关打开,有如下效果:

  • [true,true,]等价于[true, true]
  • {"a": true,}等价于{"a": true}

当这个特征和上面的ALLOW_MISSING_VALUES特征同时使用时,本特征优先级更高。也就是说:会先去除掉最后一个逗号后,再进行数组长度的计算。

举个例子:当然这两个特征开关都打开时,[true,true,]等价于[true, true]好理解;并且呢,[true,true,,]是等价于[true, true, null]的哦,可千万别忽略最后的这个null

@Test
public void test7() throws IOException {
String jsonStr = "{\"results\" : [true,true,,] }"; JsonFactory factory = new JsonFactory();
try (JsonParser jsonParser = factory.createParser(jsonStr)) {
jsonParser.enable(JsonParser.Feature.ALLOW_MISSING_VALUES);
// jsonParser.enable(JsonParser.Feature.ALLOW_TRAILING_COMMA); while (jsonParser.nextToken() != JsonToken.END_OBJECT) {
String fieldname = jsonParser.getCurrentName();
if ("results".equals(fieldname)) {
jsonParser.nextToken(); while (jsonParser.nextToken() != JsonToken.END_ARRAY) {
System.out.println(jsonParser.getBooleanValue());
}
}
}
}
}

运行程序,输出:

YourBatman
null
A哥
null
null

这完全就是上例的效果嘛。现在我放开注释掉的代码,再次运行,结果为:

YourBatman
null
A哥
null

请注意对比前后的结果差异,并自己能能自己合理解释

校验相关

Jackson在JSON标准之外,给出了两个校验相关的特征。

STRICT_DUPLICATE_DETECTION(false)

自2.10版本后,使用StreamReadFeature#STRICT_DUPLICATE_DETECTION代替

是否允许JSON串有两个相同的属性key,默认是允许的

@Test
public void test8() throws IOException {
String jsonStr = "{\"age\":18, \"age\": 28 }"; JsonFactory factory = new JsonFactory();
try (JsonParser jsonParser = factory.createParser(jsonStr)) {
// jsonParser.enable(JsonParser.Feature.STRICT_DUPLICATE_DETECTION); while (jsonParser.nextToken() != JsonToken.END_OBJECT) {
String fieldname = jsonParser.getCurrentName();
if ("age".equals(fieldname)) {
jsonParser.nextToken();
System.out.println(jsonParser.getIntValue());
}
}
}
}

运行程序,正常输出:

18
28

若放开注释代码,再次运行,则抛错:

18 // 第一个数字还是能正常输出的哟

com.fasterxml.jackson.core.JsonParseException: Duplicate field 'age'
at [Source: (String)"{"age":18, "age": 28 }"; line: 1, column: 17]

IGNORE_UNDEFINED(false)

自2.10版本后,使用StreamReadFeature#IGNORE_UNDEFINED代替

是否忽略没有定义的属性key。和JsonGenerator.Feature#IGNORE_UNKNOWN的这个特征一样,它作用于预先定义了格式的数据类型,如Avro、protobuf等等,JSON是不需要预先定义的哦~

同样的,你可以通过这个API预先设置格式:

JsonParser:

    public void setSchema(FormatSchema schema) {
...
}

其它

INCLUDE_SOURCE_IN_LOCATION(true)

自2.10版本后,使用StreamReadFeature#INCLUDE_SOURCE_IN_LOCATION代替

是否构建JsonLocation对象来表示每个part的来源,你可以通过JsonParser#getCurrentLocation()来访问。作用不大,就此略过。

总结

本文介绍了底层流式API JsonParser读JSON的方式,它不仅仅能够处理标准JSON,也能通过Feature特征值来控制,开启对一些非标准但又比较常用的JSON串的支持,这不正式一个优秀框架/库应有的态度麽:兼容性

结合上篇文章对写JSON时JsonGenerator的描述,能够总结出两点原则:

  • 写:100%遵循规范
  • 读:最大程度兼容并包

写代表你的输出,遵循规范的输出能确保第三方在用你输出的数据时不至于对你破口大骂,所以这是你应该做好的本分。读代表你的输入,能够处理规范的格式是你的职责,但我若还能额外的处理一些非标准格式(一般为常用的),那绝对是闪耀点,也就是你给的情分。本分是你应该做的,而情分就是你的加分项。

相关推荐:

4. JSON字符串是如何被解析的?JsonParser了解一下的更多相关文章

  1. json数组和json字符串转换成map解析

    package demo; import java.util.List;import java.util.Map;import java.util.Map.Entry; import net.sf.j ...

  2. mysql解析json字符串相关问题

    很多时候,我们需要在sql里面直接解析json字符串.这里针对mysql5.7版本的分水岭进行区分. 1.对于mysql5.7以上版本 使用mysql的内置函数JSON_EXTRACT(column, ...

  3. Scala中使用fastJson 解析json字符串

    Scala中使用fastJson 解析json字符串 添加依赖 2.解析json字符 2.1可以通过JSON中的parseObject方法,把json字符转转换为一个JSONObject对象 2.2然 ...

  4. 前台处理json字符串的几种方法(转)

    原文地址http://www.css88.com/archives/3919 比如我有两个变量,我要将a转换成字符串,将b转换成JSON对象: var a={"name":&quo ...

  5. JSON字符串和对象之间的转换

    JSON(JavaScript Object Notation) 是JavaScript编程语言的一个子集.正因JSON是JavaScript的一个子集,所以它可清晰的运用于此语言中. eval函数 ...

  6. 也谈C#之Json,从Json字符串到类代码

    原文:也谈C#之Json,从Json字符串到类代码  阅读目录 json转类对象 逆思考 从json字符串自动生成C#类  json转类对象 自从.net 4.0开始,微软提供了一整套的针对json进 ...

  7. json字符串、json对象、数组之间的转换

    json字符串转化成json对象 // jquery的方法 var jsonObj = $.parseJSON(jsonStr) //js 的方法 var jsonObj = JSON.parse(j ...

  8. JSON字符串和Javascript对象字面量

    JSON字符串和Javascript对象字面量 JSON是基于Javascript语法的一个子集而创建的,特别是对象和数组字面量语法. 正是由于JSON的这种特殊来历,导致很多Javascript程序 ...

  9. javascript:json对象和json字符串的相互转换

    json对象和字符串的相互转换 //使用json中的parser方法转换: var str='{"name":"fendouer", "age&quo ...

随机推荐

  1. 【部分】@using (Html.BeginForm())参数示例

    原文:https://www.cnblogs.com/firstcsharp/p/3238321.html 1.指定表单提交方式和路径等 @using (Html.BeginForm("In ...

  2. ibit-mybatis 2.x 介绍

    原文链接:ibit-mybatis 2.x 介绍 概述 ibit-mybatis 是一个 Mybatis 的增强工具,在 Mybatis 的基础上增加了新的特性与功能,志在简化开发流程.提高开发效率. ...

  3. 如何修复 WordPress 中的 HTTP 错误

    如何修复我们会向你介绍,如何在 Linux VPS 上修复 WordPress 中的 HTTP 错误. 下面列出了 WordPress 用户遇到的最常见的 HTTP 错误,我们的建议侧重于如何发现错误 ...

  4. 利用CSS变量实现炫酷的悬浮效果

    最近,我从 Grover网站 上发现以一个好玩儿的悬停动画,这个动画是将鼠标移动到订阅按钮上移动光标,会跟随光标实现相应的彩色渐变. 这个想法很简单,但是它能使这个按钮脱颖而出,人们一下子就注意到它了 ...

  5. 编写优秀CSS代码的8个策略

    编写基本的CSS和HTML是我们作为Web开发人员学习的首要事情之一.然而,我遇到的很多应用程序显然没有人花时间真正考虑前端开发的长久性和可维护性. 我认为这主要是因为许多开发人员对组织CSS / H ...

  6. cmake的下载和安装

    背景: 最近迷上了 vscode 编辑器, 快速便捷,而且插件丰富,使用起来很爽.既然这样,本身游戏也是用 mingw 加 cygwin 开发的, 可以配置一下,开搞. 实操: 1.登陆cmake官网 ...

  7. MySQL 快速删除大量数据(千万级别)的几种实践方案

    笔者最近工作中遇见一个性能瓶颈问题,MySQL表,每天大概新增776万条记录,存储周期为7天,超过7天的数据需要在新增记录前老化.连续运行9天以后,删除一天的数据大概需要3个半小时(环境:128G, ...

  8. java 面向对象(七):类结构 方法(四)递归方法

    1.定义:递归方法:一个方法体内调用它自身.2.如何理解递归方法?> 方法递归包含了一种隐式的循环,它会重复执行某段代码,但这种重复执行无须循环控制.> 递归一定要向已知方向递归,否则这种 ...

  9. celery 基础教程(三):配置

    前言 如果你使用默认的加载器,你必须创建 celeryconfig.py 模块并且保证它在python路径中. 一.加载配置方法  1.基础方法  可以设置一些选项来改变 Celery 的工作方式.这 ...

  10. Python之爬虫(七)正则的基本使用

    什么是正则表达式 正则表达式是对字符串操作的一种逻辑公式,就是 事先定义好的一些特定字符.及这些特定字符的组合,组成一个“规则字符”,这个“规则字符” 来表达对字符的一种过滤逻辑. 正则并不是pyth ...