|
| 1 | +--- |
| 2 | +title: fastjson |
| 3 | +lock: need |
| 4 | +--- |
| 5 | + |
| 6 | +# fastjson 使用 |
| 7 | + |
| 8 | +作者:小傅哥 |
| 9 | +<br/>博客:[https://bugstack.cn](https://bugstack.cn) |
| 10 | + |
| 11 | +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 |
| 12 | +
|
| 13 | +本文的宗旨在于通过简单干净实践的方式教会读者,使用 fastjson 的一些常用操作方法。这些方法也是日常使用 fastjson 时最为常用的方法,如果你在使用中还有一些案例和特性,或者踩坑经验也可以在本文提交PR |
| 14 | + |
| 15 | +本文涉及的工程: |
| 16 | + |
| 17 | +- xfg-dev-tech-fastjson:[https://gitcode.net/KnowledgePlanet/road-map/xfg-dev-tech-fastjson](https://gitcode.net/KnowledgePlanet/road-map/xfg-dev-tech-fastjson) |
| 18 | +- Github:[https://github.com/alibaba/fastjson](https://github.com/alibaba/fastjson) |
| 19 | + |
| 20 | +## 一、常用方法 |
| 21 | + |
| 22 | +### 1. 序列化和反序列化 |
| 23 | + |
| 24 | +```java |
| 25 | +String strJson = JSON.toJSONString(UserEntity.builder().build()); |
| 26 | +UserEntity userEntity = JSON.parseObject(strJson, UserEntity.class); |
| 27 | +``` |
| 28 | + |
| 29 | +### 2. 配置序列化字段 |
| 30 | + |
| 31 | +```java |
| 32 | +// 不被序列化 |
| 33 | +@JSONField(name="amount", serialize=false) |
| 34 | +private Double amount; |
| 35 | +// 序列化格式 |
| 36 | +@JSONField(name="createTime", format="dd/MM/yyyy", ordinal = 3) |
| 37 | +private Date createTime; |
| 38 | + |
| 39 | +@JsonProperty("top_p") |
| 40 | +private Double topP = 1d; |
| 41 | +@JsonProperty("max_tokens") |
| 42 | +private Integer maxTokens = 2048; |
| 43 | +``` |
| 44 | + |
| 45 | +- 对象的属性上添加 `@JSONField`、`@JsonProperty` 都可以改变序列化字段的名字。同时还可以扩展是否被序列化和格式化。 |
| 46 | + |
| 47 | +### 3. 排除序列化字段 |
| 48 | + |
| 49 | +```java |
| 50 | +UserEntity userEntity = UserEntity.builder() |
| 51 | + .amount(100D) |
| 52 | + .userName("xfg") |
| 53 | + .password("abc000") |
| 54 | + .createTime(new Date()) |
| 55 | + .build(); |
| 56 | + |
| 57 | +SimplePropertyPreFilter filter = new SimplePropertyPreFilter(); |
| 58 | +Collections.addAll(filter.getExcludes(), "password"); |
| 59 | +log.info(JSON.toJSONString(userEntity, filter)); |
| 60 | +``` |
| 61 | + |
| 62 | +- 因为有些时候不是你能修改被序列化的对象,如你引入了别人的 JAR 之后需要对某个类进行序列化,但因为有些对象不能被序列化或者不要序列化。那么这个时候就可以通过 filter 过滤的方式进行处理。 |
| 63 | + |
| 64 | +### 4. json2map 转换 |
| 65 | + |
| 66 | +```java |
| 67 | +@Test |
| 68 | +public void test_map2json() { |
| 69 | + Map<String, Object> map = new HashMap<>(); |
| 70 | + map.put("key1", "xfg"); |
| 71 | + map.put("key2", 123); |
| 72 | + map.put("key3", false); |
| 73 | + log.info(JSON.toJSONString(map)); |
| 74 | +} |
| 75 | + |
| 76 | +@Test |
| 77 | +public void test_json2map() { |
| 78 | + String jsonString = "{\"key1\":\"xfg\",\"key2\":123,\"key3\":false}"; |
| 79 | + Map<String, Object> map = JSON.parseObject(jsonString, Map.class); |
| 80 | + for (Map.Entry<String, Object> entry : map.entrySet()) { |
| 81 | + log.info("{} : {}", entry.getKey(), entry.getValue()); |
| 82 | + } |
| 83 | +} |
| 84 | +``` |
| 85 | + |
| 86 | +- 有些时候我们接收的对象就是个 Map 那么你可以使用 fastjson 来对对象进行 map 的转换或者序列化 |
| 87 | + |
| 88 | +### 5. toString 处理 |
| 89 | + |
| 90 | +```java |
| 91 | +@Test |
| 92 | +public void testToString2Bean() throws Exception { |
| 93 | + UserEntity userEntity = UserEntity.builder() |
| 94 | + .amount(100D) |
| 95 | + .userName("xfg") |
| 96 | + .password("abc000") |
| 97 | + .createTime(new Date()) |
| 98 | + .build(); |
| 99 | + log.info(userEntity.toString()); |
| 100 | + log.info(JSON.toJSONString(ToString2Bean.toObject(userEntity.toString(), UserEntity.class))); |
| 101 | +} |
| 102 | + |
| 103 | +public static <T> T toObject(String str, Class<T> clazz) throws Exception { |
| 104 | + // 创建一个新的对象 |
| 105 | + T obj = clazz.getDeclaredConstructor().newInstance(); |
| 106 | + // 获取类对象 |
| 107 | + Class<?> objClass = obj.getClass(); |
| 108 | + // 解析字符串 |
| 109 | + String[] fields = str.substring(str.indexOf("{") + 1, str.indexOf("}")).split(", "); |
| 110 | + // 遍历成员变量 |
| 111 | + for (String field : fields) { |
| 112 | + // 获取成员变量名和值 |
| 113 | + String[] parts = field.split("="); |
| 114 | + // 获取成员变量对象 |
| 115 | + Field objField = objClass.getDeclaredField(parts[0].trim()); |
| 116 | + // 设置成员变量可以访问 |
| 117 | + objField.setAccessible(true); |
| 118 | + // 设置成员变量的值 |
| 119 | + objField.set(obj, convertValue(objField.getType(), parts[1].trim())); |
| 120 | + // 设置成员变量不可访问 |
| 121 | + objField.setAccessible(false); |
| 122 | + } |
| 123 | + return obj; |
| 124 | +} |
| 125 | +``` |
| 126 | + |
| 127 | +```java |
| 128 | +06:03:46.302 [main] INFO cn.bugstack.xfg.dev.tech.test.ApiTest - UserEntity{userName='xfg', password='abc000', amount=100.0, createTime=2023-09-21 20:03:46} |
| 129 | +06:03:46.670 [main] INFO cn.bugstack.xfg.dev.tech.test.ApiTest - {"password":"'abc000'","userName":"'xfg'","createTime":"21/09/2023"} |
| 130 | + |
| 131 | +Process finished with exit code 0 |
| 132 | +``` |
| 133 | + |
| 134 | +- 有一些在方法入参的时候需要用日志打印入参信息。大部分时候都是直接用 json 打印对象,但对于一些较大对象就比较耗时。所以阿里的开发手册是建议这个场景使用 toString 操作。 |
| 135 | +- 但是 toString 操作后的日志不太便于,在本地进行测试验证。因为不好转对象。所以这里我们写个 toString2Bean 对象的方法。 |
| 136 | + |
0 commit comments