• GsonUtils和字符串


    1、GsonUtils

    • Json字符串转对象
    • 对象转Json字符串
    @UtilityClass
    @Slf4j
    public class GsonUtils {
        private static final Gson GSON = new Gson();
    
        public static String toJsonStr(Object object) {
            return GSON.toJson(object);
        }
    
        public static String toJsonStr(Object obj, Type type) {
            return GSON.toJson(obj, type);
        }
    
        public static <T> T fromJson(String json, Class<T> classOfT) {
            return GSON.fromJson(json, classOfT);
        }
    
        public static <T> T fromJson(String json, Type typeOfT) {
            return GSON.fromJson(json, typeOfT);
        }
    
        public static String toJson(Object object) {
            try {
                return GSON.toJson(object);
            } catch (Exception e) {
                log.error("序列化失败", e);
            }
            return StringUtils.EMPTY;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 工具类使用
    String str = "{\"status\":{\"code\":0,\"__isset_bit_vector\":[1]},\"poiId\":1}";
     TResponse tResponseA = GsonUtils.fromJson(str, TResponse.class);
    
    • 1
    • 2

    2、String本身,可以加入日志信息

    String.format("Duplicate asyncCreateTask request with requestId=%s, billNo=%s, finish it fast.", request.getRequestId(), request.getNo());
    
    • 1

    3、 Json和Map转换

    map.put("0915", "1");
    map.put("0916", "2");
    String jsonStr = GsonUtils.toJsonStr(map);
    Map json2Map = GsonUtils.fromJson(jsonStr,new TypeToken>(){}.getType());
    
    • 1
    • 2
    • 3
    • 4

    4、Date转为Json字符串

    如果类中有Date类型的属性字段,则需要在创建gson的时候设置一下日期格式
        Gson gson = new GsonBuilder()
            .setDateFormat("yyyy-MM-dd")
            .create();
        System.out.println(gson.toJson(new Date()));
    
    • 1
    • 2
    • 3
    • 4
    • 5

    5、Json和List转换

    List<SkuDTO> list = GsonUtils.fromJson(jsonStr,new TypeToken<List<SkuDTO>>(){}.getType());
    
    List<Long> list2 = GsonUtils.fromJson(Lists.newArrayList(1L,2L), new TypeToken<List<Long>>() {}.getType());
    
    • 1
    • 2
    • 3

    6、 比较两个JSON字符串的不同

    public void t() throws JSONException {
            String s1 = "{\"skuId\":1,\"skuName\":\"test\",\"temp\":2,\"address\":\"bj\"}";
            String s2 = "{\"skuId\":1,\"skuName\":\"test\",\"temp\":3,\"author\":\"mjp\"}";
    
            // 方式一:
            JSONCompareResult result  = JSONCompare.compareJSON(s1, s2, JSONCompareMode.STRICT);
              <dependency>
                <groupId>org.skyscreamer</groupId>
                <artifactId>jsonassert</artifactId>
                <version>1.5.1</version>
                <scope>test</scope>
            </dependency>
    
            // 1中有2中没有
            System.out.println(result.isMissingOnField());
            List<FieldComparisonFailure> fieldMissing = result.getFieldMissing();
            for (FieldComparisonFailure fieldComparisonFailure : fieldMissing) {
                System.out.println(fieldComparisonFailure.getExpected());//address
            }
    
            // 2中有1中没有
            System.out.println(result.isUnexpectedOnField());
            List<FieldComparisonFailure> fieldUnexpected = result.getFieldUnexpected();
            for (FieldComparisonFailure fieldComparisonFailure : fieldUnexpected) {
                System.out.println(fieldComparisonFailure.getActual());//author
            }
    
            // 1中2中都有,但是val值不一样
            System.out.println(result.isFailureOnField());
            List<FieldComparisonFailure> list = result.getFieldFailures();
            for (FieldComparisonFailure fieldComparisonFailure : list) {
                System.out.println(fieldComparisonFailure.getField());//temp
                System.out.println(fieldComparisonFailure.getActual());//3
                System.out.println(fieldComparisonFailure.getExpected());//2
            }
    
    
            // 方式二:
            HashMap<String, Object> diffMap = Maps.newHashMap();
            Gson gson = new Gson();
            Map<String,Object> json1Map = gson.fromJson(s1,new TypeToken<HashMap<String,Object>>(){}.getType());
            Map<String,Object> json2Map = gson.fromJson(s2,new TypeToken<HashMap<String,Object>>(){}.getType());
    
            for (Map.Entry<String, Object> entry : json1Map.entrySet()) {
                String k1 = entry.getKey();
                Object v1 = entry.getValue();
                Object v2 = json2Map.get(k1);
                // 1中有2中没有
                if (v2 == null) {
                    diffMap.put(k1, v1);
                    continue;
                }
    
                // 1中2中都有,但是不一样
                if (!Objects.equals(v1, v2)){
                    diffMap.put(k1, "expect:" + v1 + ", actual:" + v2);
                }
            }
            json2Map.forEach((k2, v2) -> {
                Object v1 = json1Map.get(k2);
                // 2中有1中没有
                if (v1 == null) {
                    diffMap.put(k2, v2);
                }
            });
    
            System.out.println(diffMap);//{temp=expect:2.0, actual:3.0, address=bj, author=mjp}
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68

    7、 字符串填充:生成单据号时填充

    Long billType = 1L;
    System.out.println("a" + StringUtils.leftPad(billType + "", 5, "0"));// a00001
    即在billType的左侧补0,直到00001形成5位为止
    右侧填充和两侧填充api如下:
    public static String leftPad(final String str, final int size, String padStr)
     public static String center(String str, final int size, String padStr)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    8、 String.format()的使用

    参考:https://blog.csdn.net/lonely_fireworks/article/details/7962171

    • 简单使用
    int time = 3;
    String nameParis = String.format("达到了最大次数%s次", time);
    
    • 1
    • 2
    • 复杂使用
    String contentFormat = "您今天售卖的【%s】支商品有较高可能发生售罄,预估销售损失pcs【%s】件,预估销售损失额【%s" +"】元,需联系补货,请点击“[及时处理|%s]”查看详情。";
    
    String url = "sell.out.warning.link:https://xxx.xxx.xxx" + ".com?warnType=%s&categoryId=%s"
    
    String result = String.format(contentFormat, skuCount, salePcs.stripTrailingZeros().toPlainString(),
                    saleGmv.stripTrailingZeros().toPlainString(),
                    String.format(url, warnType, categoryId));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    1、将warnTpe和categoryId,填充到url中,成为一个完整的连接url

    2、sku数,pcs,GMV,及时处理链接url 四个字端值,填充到contentFormat的%s中

    9、截断字符串

    String s = "大家好才是真的好";
    String truncate = StringUtils.truncate(s, 2, 4);
    System.out.println(truncate);//好才是真
    
    • 1
    • 2
    • 3

    10、split

    https://www.runoob.com/java/java-string-split.html

    isNotBlank 和 isNotEmpty的区别

    public static boolean isNotEmpty(String str):判断某字符串是否非空,这里不能排除空格字符,即StringUtils.isNotEmpty("  ") = true
      下面是示例:
    StringUtils.isNotEmpty(null) = false
    StringUtils.isNotEmpty("") = false
    StringUtils.isNotEmpty(" ") = true
    
      
    public static boolean isNotBlank(String str)
    判断某字符串是否不为空且长度不为0且不由空白符(whitespace)构成,即StringUtils.isNotBlank("  ") = false
     下面是示例:
    StringUtils.isNotBlank(null) = false
    StringUtils.isNotBlank("") = false
    StringUtils.isNotBlank(" ") = false
     
    所以,在某些业务场景,用isNotBlank 比 isNotEmpty要好
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    11、判断字符串是否为Json字符串格式

    try {
         JsonElement parse = new JsonParser().parse(extra);
          if (parse.isJsonObject() || parse.isJsonArray()) {
                    //YES
           }
    } catch (JsonSyntaxException e) {
                //ignore
    }
    // NO
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    12、deep copy

            // 对象deep copy
            MyUser myUser = new MyUser();
            myUser.setSkuId(1L);
    
            Gson gson = new Gson();
            MyUser newUser = gson.fromJson(gson.toJson(myUser), MyUser.class);
            System.out.println(newUser);
            myUser.setSkuId(77777777777L);
            System.out.println(newUser);
    
            // 集合deep copy
            List<MyUser> newList = JSON.parseArray(JSON.toJSONString(list), MyUser.class);//fastjson
            System.out.println(newList);
            u1.setSkuId(777777777777777L);
            System.out.println(newList);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    13、DecimalFormat

    用于数字的转字符串展示

    • 后端返回的BigDecimal在前端,四舍五入的展示
    • 1,000,000这种格式展示
    • 取小数点后几位等。
      涉及到字符串的格式展示的,可以使用

    14、字符串的连接

    1、s1 + s2 + s3会被自动优化为sb.append(s1).append(s2).append(s3).toString()

    由于字符串的不可变性,连接 n 个字符串重复使用字符串连接操作,需要 n2 的时间。

    sb 对象内部维护一个字符数组。操作都是在字符数组上进行,append 方法的时间是线性的

    2、字符串不适合替代其他值类型,数据本质上确实是文本信息时,使用字符串才合理

    3、参考:唯品会的工具类StringBuilder在高性能场景下的引用

    https://github.com/vipshop/vjtools/blob/master/vjkit/src/main/java/com/vip/vjtools/vjkit/text/StringBuilderHolder.java
    
    • 1

    补充:关于msyql的Json格式

    将json格式的内容存储mysql,mysql中字段为json而非Varchar

    • 推荐5.7之后直接使用 字段名称 json
    • 一般都用varchar(n) 注:n不要太大。太大的话考虑 JSON
  • 相关阅读:
    追求性能极致:Redis6.0的多线程模型
    数据量大、类型多!数据资产管理如何确保安全合规“不掉队”?
    MySQL存储架构
    Codeforces Round 901 (Div. 2) - C. Jellyfish and Green Apple - 思维+位运算
    从零开始学Spring Boot系列-返回json数据
    966SEO扫地僧站群·万能HTML模板[V1.9.1]
    ArcGIS Pro导出布局时去除在线地图水印
    Windows 根据dll生成 lib文件
    C# 串口接收1次数据会进入2次串口接收事件serialPort1_DataReceived,第2次进入时串口缓冲区为空
    MYSQL 数据库各类属性说明 (持续更新)
  • 原文地址:https://blog.csdn.net/tmax52HZ/article/details/133210768