json格式转换文本的方法 jsonobject解析json字符串特别慢


json格式转换文本的方法 jsonobject解析json字符串特别慢


版本约定
  • Jackson 版本:2.11.0
  • Spring Framework 版本:5.2.6.RELEASE
  • Spring Boot 版本:2.3.0.RELEASE
什么叫读 JSON?就是把一个 JSON 字符串 解析为对象 or 树模型嘛,因此也称作解析 JSON 串 。Jackson 底层流式 API 使用JsonParser来完成JSON 字符串的解析 。
最简使用 Demo准备一个 POJO:
@Datapublic class Person {private String name;private Integer age;}测试用例:把一个 JSON 字符串绑定(封装)进一个 POJO 对象里
@Testpublic 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@Overridepublic T readValue(JsonParser jsonParser, Class 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;}...}