https://zhuanlan.zhihu.com/p/259511591

实体类

package com.example.demo.baen;import lombok.Data;/*** 用户信息*/
@Data
public class UserInfo {private String id;private String phoneNumber;private String nickName;private String photoAddress;public UserInfo(String id, String phoneNumber, String nickName, String photoAddress) {this.id = id;this.phoneNumber = phoneNumber;this.nickName = nickName;this.photoAddress = photoAddress;}public UserInfo() {}
}

测试方法

public static void main(String[] args) throws ParseException {UserInfo userInfo = new UserInfo();userInfo.setId("1019174798796259328");userInfo.setNickName("18237258755");userInfo.setPhoneNumber("18237258755");userInfo.setPhotoAddress("123456");//  UserInfo(id=1019174798796259328, phoneNumber=18237258755, nickName=18237258755, photoAddress=123456)String s = String.valueOf(userInfo);String s1 = ToStringUtils.toJSONString(s);// {"phoneNumber":"18237258755","nickName":"18237258755","id":"1019174798796259328","photoAddress":"123456"}System.out.println(s1);UserInfo info = JSON.parseObject(s1, UserInfo.class);// trueSystem.out.println(info instanceof UserInfo);}

试想一个问题:如果我们已知Java对象的toString格式,想要获取其json格式或者其Java对象,该如何做呢?

注意:Java对象的toString格式目前没有规范规定其格式,毕竟可以自定义对象toString方法,不过一般情况下对象的toString的格式如下所示。通过toString获取Java对象的话,只要将toString转json后再通过JSON.parseObject()转成对象即可,现在剩下的问题就是toString转json了。

@Data
public class Person {private String name = "张三";private Integer age = 27;
}
toString: Person(name=张三, age=27)

在具体分析toString转json问题之前,我们首先来看下Java中常见的几种数据序列化格式吧,日常开发中接触到的对象格式主要分为以下两大类:

强类型格式:java Serializable、hession、Thrift、Protobuf等。
弱类型格式:json、xml等。

上述数据类型格式基本都对应至少1个序列化框架或工具,比如json序列化框架就包括fastjson、Jackson、Gson等。那么本文探讨的toString格式应该分为那种类型格式呢?

相信很多小伙伴心中都已有答案,没错,toString就是弱类型格式。那么针对上面提到的toString转json,换句话说,也就是toString反序列化为json,就可以参考类似json的反序列化机制来完成。

首先要明确的是,由于toString格式不统一,因此我们使用最常见的toString格式,也就是 Person(name=张三, age=27) 这种。toString转json步骤如下:

  1. 首先要将toString字符串解析成一个个token,token就是key=value这种格式,比如上述中的 “name=张三” 字符串,不管key和value是基本类型还是对象,都是一个token;
  2. 其次将一个token解析成key和value,通过分隔符 “=” 来分割;
  3. 然后将key和value转换为json的单个token结构,也就是"key":"value"这种格式。注意这里的key或者value可能不是基本类型,因此需要继续递归处理;

注意:除了单个token之外,还有list和map结构的数据,只不过其是token列表和token map结构而已。针对value是"null"字符串,当做空值null来处理。
由于toString是弱类型数据格式,toString格式中key=value,比如key=100,这个value 100无法区分出来是数值类型还是字符串类型,保险起见将其处理成字符串类型,由于(fastjson中)JSON反序列化支持这种处理格式,因此将其设置成字符串是OK的。

具体的toString转json代码实现如下(Java实现):

package com.example.demo.utils;import com.alibaba.fastjson.JSON;
import javafx.util.Pair;
import org.apache.commons.lang3.StringUtils;import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Pattern;public class ToStringUtils {/*** toString格式反序列化*//*** 数字类型匹配(包括整形和浮点型) & 日期类型匹配 & 对象类型匹配 & ...*/public static Pattern datePattern = Pattern.compile("^[a-zA-Z]{3} [a-zA-Z]{3} [0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2} CST ((19|20)\\d{2})$");public static Pattern numPattern = Pattern.compile("^-?[0-9]+\\.?[0-9]*$");public static Pattern objectPattern = Pattern.compile("^[a-zA-Z0-9\\.]+\\(.+\\)$");public static Pattern listPattern = Pattern.compile("^\\[.*\\]$");public static Pattern mapPattern = Pattern.compile("^\\{.*\\}$");public static Pattern supperPattern = Pattern.compile("^super=[a-zA-Z0-9\\.]+\\(.+\\)$");public static final String NULL = "null";/*** toString -> json*/public static String toJSONString(String toString) throws ParseException {return JSON.toJSONString(toMap(toString));}/*** toString -> object*/public static <T> T toObject(String toString, Class<T> clazz) throws ParseException {return JSON.parseObject(toJSONString(toString), clazz);}/*** toString -> map*/private static Map<String, Object> toMap(String toString) throws ParseException {if (StringUtils.isEmpty(toString = StringUtils.trim(toString))) {return toString == null ? null : new HashMap<>();}// 移除最外层"()"toString = StringUtils.substringAfter(toString, "(").trim();toString = StringUtils.substringBeforeLast(toString, ")").trim();String token;Map<String, Object> map = new HashMap<>();while (StringUtils.isNotEmpty(toString) && StringUtils.isNotEmpty(token =splitToken(toString))) {toString = StringUtils.removeStart(StringUtils.removeStart(toString, token).trim(), ",").trim();// 如果带"super="(lombok的@ToString(callSuper=true)引入),按照当前层继续处理if (supperPattern.matcher(token).matches()) {token = token.substring(token.indexOf("(") + 1, token.length() - 1);toString = String.format("%s,%s", token, toString);continue;}Pair<String, String> keyValue = parseToken(token);map.put(keyValue.getKey(), buildTypeValue(keyValue.getKey(), keyValue.getValue()));}return map;}static Pair<String, String> parseToken(String token) {assert Objects.nonNull(token) && token.contains("=");int pos = token.indexOf("=");return new javafx.util.Pair<>(token.substring(0, pos), token.substring(pos + 1));}/*** 单个token解析** @param key 可根据key设置自定义序列化操作*/private static Object buildTypeValue(String key, String value) throws ParseException {if (StringUtils.isEmpty(value)) {return null;} else if (value.equals(NULL)) {return null;}// 日期类型if (datePattern.matcher(value).matches()) {return new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy", new Locale("us")).parse(value).getTime();}// 数字类型if (numPattern.matcher(value).matches()) {return value;}// 集合类型if (listPattern.matcher(value).matches()) {return buildListValue(value);}// map类型if (mapPattern.matcher(value).matches()) {return buildMapValue(value);}// 对象类型if (objectPattern.matcher(value).matches()) {return toMap(value);}// 其他都认为是string类型return value;}/*** 集合类型*/private static Object buildListValue(String value) throws ParseException {List<Object> result = new ArrayList<>();value = value.substring(1, value.length() - 1).trim();if (StringUtils.isEmpty(value)) {return result;}String token = null;while (StringUtils.isNotBlank(value) && StringUtils.isNotBlank(token = splitToken(value))) {result.add(buildTypeValue(null, token));value = StringUtils.removeStart(StringUtils.removeStart(value, token).trim(), ",").trim();}return result;}static String splitToken(String toString) {if (StringUtils.isBlank(toString)) {return toString;}int bracketNum = 0;Stack<Character> stack = new Stack<>();for (int i = 0; i < toString.length(); i++) {Character c = toString.charAt(i);if (tokenMap.containsValue(c)) {stack.push(c);} else if (tokenMap.containsKey(c) && Objects.equals(stack.peek(), tokenMap.get(c))) {stack.pop();} else if ((c == ',') && stack.isEmpty()) {return toString.substring(0, i);}}if (stack.isEmpty()) {return toString;}throw new RuntimeException("splitFirstToken error, bracketNum=" + bracketNum + ", toString=" + toString);}/*** 获取第一个token,注意: toString不再包括最外层的()*/private final static Map<Character, Character> tokenMap = new HashMap<>();static {tokenMap.put(')', '(');tokenMap.put('}', '{');tokenMap.put(']', '[');}/*** map类型*/private static Map<Object, Object> buildMapValue(String value) throws ParseException {Map<Object, Object> result = new HashMap<>();value = value.substring(1, value.length() - 1).trim();if (StringUtils.isEmpty(value)) {return result;}String token = null;while (StringUtils.isNotEmpty(token =splitToken(value))) {Pair<String, String> keyValue =parseToken(token);result.put(buildTypeValue(keyValue.getKey(), keyValue.getKey()), buildTypeValue(keyValue.getKey(), keyValue.getValue()));value = StringUtils.removeStart(StringUtils.removeStart(value, token).trim(), ",").trim();}return result;}}

依赖jar包有commons-lang3、fastjson

最后,toString转json有哪些应用场景呢?

日常开发中有些场景可能需要将java对象的toString格式转换为json格式来使用,毕竟json格式较为通用并且很容易将其反序列化为对应Java对象,常见的场景有:写单测时,mock一个复杂对象,从日志中可以获取到了对象toString格式,但是需要的是json格式或者对象格式。

toString转化成json相关推荐

  1. jQuery:将文本转化成JSON对象应注意的问题

    在jQuery的许多方法中,很多方法的参数可以传入一个JSON对象,比如Ajax方法的第二个参数.怎么将文本转化成JSON对象,需要注意以下问题: 1)$.parseJSON方法返回的是一个字符串,而 ...

  2. java 序列化成xml文件_将Java对象序列化成JSON和XML格式

    1.先定义一个Java对象Person: public class Person { String name; int age; int number; public String getName() ...

  3. oracle json字符串转数组,json字符串转化成json对象(原生方法)

    json字符串.json对象.数组 三者之间的转换 //json字符串.json对象.数组 三者之间的转换 let jsonStr = '[{"id":"01" ...

  4. fastjson把对象转化成json避免$ref

    转:fastjson把对象转化成json避免$ref DisableCircularReferenceDetect来禁止循环引用检测: JSON.toJSONString(..., Serialize ...

  5. 提取tsv数据并转化成json——致找不出怎么提取tsv文件中数据的五小时

    这里使用的python3.6,pycharm2017profession(不知道其他版本是否适合) 接下来进入正题: 导入tsv.re.json库 首先,由于python3.6没有tsv库,所以使用命 ...

  6. python转json中文乱码_python 序列化成json 乱码问题的解决

    今天又网友问到, 在python 下将一个对象序列化成 json 时经常会报乱码, 甚至会报错, 的确会出现这种情况,因为在python 中默认使用的是 simplejson 库.但其实是可以通过配置 ...

  7. TimeStamp日期类型转化成json

    1. 新建处理timestamp类型的处理类 import java.text.SimpleDateFormat;import java.util.Date;import net.sf.json.Js ...

  8. java中字符串String格式转化成json格式

    一.将Sting转为Json 在开发中,经常是前端发送一串数据过来之后,是通过一个参数带着一串值过来,这一串值是String 格式的,但是里面的内容其实是json格式类型的,所以拿到值之后就要将该值转 ...

  9. java字符串数组转json_java中字符串String格式转化成json格式

    java字符串数组转json_java中字符串String格式转化成json格式 String s= Connection.deleteHost("10310");System.o ...

最新文章

  1. Microsoft .NET Pet Shop 4 架构与技术分析
  2. taro 在components文件夹中 新建组件时,组件支持自定义命名,但是不能大写开头...
  3. android studio 混淆jar,android studio如何生成混淆代码的jar
  4. BugkuCTF-Misc:爆照(08067CTF)
  5. 像数据科学家一样思考:12步指南(上)
  6. 什么是HystrixDashbord/如何使用?
  7. 计算机与操作系统基础小结
  8. 一个大图切成几个小图加载速度更快_CSS精灵图技术(提高页面的加载速度)
  9. php封装app微信支付
  10. MovieLens数据集
  11. 今日头条推荐算法原理
  12. 爆料!爆料!亚马逊跨境电商店铺骗局被骗真相曝光!不要在上当了!
  13. RC电路一阶线性微分方程
  14. 怎么实现类似星星闪烁的效果(box-shadow)
  15. 运行wordcount时显示Could not obtain block
  16. ROS学习总结十二:给自己的机器人添加传感器
  17. FileProvider
  18. 如何学习黑客技术?初级黑客入门
  19. c语言名人名言大全摘抄,数学名人名言大全摘抄
  20. 有哪些好用的App云测试平台?

热门文章

  1. 什么是java线程_Java多线程是什么意思?
  2. PM常用语看这篇就够了
  3. Vim 匹配相同的单词并高亮
  4. Word 2016中给公式自动编号
  5. Android的.9图片使用问题
  6. 绘制线性回归和多元线性回归
  7. printf输出bool值 | printf转换符
  8. 我的浏览器 My Brower
  9. MATLAB中快捷注释方法和使用“%%”将代码分块运行方法
  10. OC5038内置 MOS 开关降压型 LED 恒流驱动器