Java 手动解析不带引号的JSON字符串的操作

1 需求说明

项目中遇到了一批不带引号的类JSON格式的字符串:

{Name:Heal,Age:20,Tag:[Coding,Reading]}

需要将其解析成JSON对象, 然后插入到Elasticsearch中, 当作Object类型的对象存储起来.

在对比了阿里的FastJson、Google的Gson, 没找到想要的功能 ( 可能是博主不够仔细, 有了解的童学留言告诉我下呀), 于是就自己写了个工具类, 用来实现此需求.

如果是带有引号的标准JSON字符串, 可直接通过上述2种工具进行解析, 使用方法可参考:

Java - 格式化输出JSON字符串的两种方式

2 解析代码

2.1 实现思路

代码的主要思路在注释中都有说明, 主要思路是:

(1) 借助Stack统计字符串首尾的[]、{}符号 —— []代表List, {}代表Map;

(2) 使用String#subString()方法缩减已解析的字符串;

(3) 使用递归解析内部的List、Map对象;

(4) 为了便于处理, 最小的key-value都解析成String类型.

需要注意的是: 要解析的字符串内部不要存在无意义的{、}、[、]符号, 否则会导致解析发生异常.

—— 暂时没想到好的兼容方法, 有想法的童学请直接留言.**

2.2 详细代码

package com.healchow.util;

import java.security.InvalidParameterException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;

/**
 * Java 解析不带引号的JSON字符串
 *
 * @author Heal Chow
 * @date 2019/08/13 11:36
 */
public class ParseJsonStrUtils {
   

 public static void main(String[] args) {
   

  // 带引号的字符串, 会将字符串当作key-value的一部分, 因此这类字符串推荐使用fastJson、Gson等工具转换
  // 注意: String内部不要存在无意义的{、}、[、]符号 - 暂时没想到好的兼容方法
  /*String sourceStr = "{\"_index\":\"book_shop\"," +
       "\"_id\":\"1\"," +
       "\"_source\":{" +
        "\"name\":\"Thinking in Java [4th Edition]\"," +
        "\"author\":\"[US] Bruce Eckel\"," +
        "\"price\":109.0,\"date\":\"2007-06-01 00:00:00\"," +
        "\"tags\":[\"Java\",[\"Programming\"]" +
       "}}";*/

  // 不带引号的字符串, 首尾多对[]、{}不影响解析
  String sourceStr = "[[[{" +
       "{" +
        "Type:1," +
        "StoragePath:[{Name:/image/2019-08-01/15.jpeg,DeviceID:4401120000130},{ShotTime:2019-08-01 14:44:24}]," +
        "Width:140" +
       "}," +
       "{" +
        "Type:2,StoragePath:9090/pic/2019_08_01/src.jpeg," +
        "Inner:{DeviceID:44011200}," +
        "Test:[{ShotTime:2019-08-01 14:50:14}]," +
        "Width:5600}" +
       "}}]]]";

  List<Map<String, Object>> jsonArray;
  Map<String, Object> jsonMap;

  Object obj = null;
  try {
   
   obj = parseJson(sourceStr);
  } catch (Exception e) {
   
   System.out.println("出错啦: " + e.getMessage());
   e.printStackTrace();
  }

  if (obj instanceof List) {
   
   jsonArray = (List<Map<String, Object>>) obj;
   System.out.println("解析生成了List对象: " + jsonArray);
  } else if (obj instanceof Map) {
   
   jsonMap = (Map<String, Object>) obj;
   System.out.println("解析生成了Map对象: " + jsonMap);
  } else {
   
   System.out.println("需要解析的字符串既不是JSON Array, 也不符合JSON Object!\n原字符串: " + sourceStr);
  }
 }

 /**
  * 解析 Json 格式的字符串, 封装为 List 或 Map 并返回
  * 注意: (1) key 和 value 不能含有 ",", key 中不能含有 ":" —— 要分别用 "," 和 ":" 进行分隔
  *  (2) 要解析的字符串必须符合JSON对象的格式, 只对最外层的多层嵌套做了简单的处理,
  *   复杂的如"{a:b},{x:y}"将不能完全识别 —— 正确的应该是"[{a:b},{x:y}]"
  * @param sourceStr 首尾被"[]"或"{}"包围的字符串
  * @return 生成的JsonObject
  */
 public static Object parseJson(String sourceStr) throws InvalidParameterException {
   
  if (sourceStr == null || "".equals(sourceStr)) {
   
   return sourceStr;
  }

  // 判断字符串首尾有没有多余的、相匹配的 "[]" 和 "{}"
  String parsedStr = simplifyStr(sourceStr, "[", "]");
  parsedStr = 

你可能感兴趣的:(Java,java,字符串,json)