识别Json字符串并分隔成Map集合

识别Json字符串并分隔成Map集合

前言:

最近又看了点Java的知识,于是想着把CYQ.Data V5迁移到Java版本。

过程发现坑很多,理论上看大部分很相似,实践上代码写起来发现大部分都要重新思考方案。

遇到的C#转Java的一些小问题:

1:C#的ref:这个参数的主要意图是:

就算方法内部重新对参数重新(new)赋值,也能保证外部的参数指向新的值。

Java木有了,不知道新的方案是什么?还是说只能避免方法内部重新(new)赋值?

2:C#的out:这个参数的主要意图是:

处理多值返回的问题。

Java木有了,只能改返回数组了。

3:C#的SqlDbType和DbType

其实我也没想过C#为什么还要搞个DbType(用在DbParameter参数上使用)

Java:涉入不深,不知道用啥代替?

4:C#的DBNull.Value

Java:好像木有这东东,用啥代替?

5:C#的ChangeType 通用类型转换

Java:涉入不深,不知道用啥代替?

6:C#的反射Type有属性可以识别是否泛型(IsGenericType)和Nullable.GetUnderlyingType(t)

Java:在Class里找不到泛型判断,替代方案是?

7:发现Map集合的大多数默认都对key进行了排序,最后发现只有这个才默认没排序:LinkedHashMap

8:关于代码折叠:

C#里用#region和#endregion。

Java里要下个插件,然后改成//region和//endregion。

9:Java木有Internal修饰符,木有Jar包内使用的修饰符,真心不友好。

10:其它的主是一些大小写和方法的改了。

好了,先小小总结到这里,下面上Java代码,主要有3个类:

1:实现代码(内部实现类):CharState

package cyq.data.tool;

/// <summary>
/// 字符状态
/// </summary>
class CharState
{
    boolean jsonStart = false;//以 "{"开始了...
    boolean setDicValue = false;// 可以设置字典值了。
    boolean escapeChar = false;//以"\"转义符号开始了
    /// <summary>
    /// 数组开始【仅第一开头才算】,值嵌套的以【childrenStart】来标识。
    /// </summary>
    boolean arrayStart = false;//以"[" 符号开始了
    boolean childrenStart = false;//子级嵌套开始了。
    /// <summary>
    /// 【0 取名称中】;【1 取值中】
    /// </summary>
    int state = -1;

    /// <summary>
    /// 【-1 未初始化】【0 未开始】【1 无引号开始】【2 单引号开始】【3 双引号开始】
    /// </summary>
    int keyStart = -1;
    /// <summary>
    /// 【-1 未初始化】【0 未开始】【1 无引号开始】【2 单引号开始】【3 双引号开始】
    /// </summary>
    int valueStart = -1;
    boolean isError = false;//是否语法错误。

    void CheckIsError(char c)//只当成一级处理(因为GetLength会递归到每一个子项处理)
    {
        switch (c)
        {
            case ‘{‘://[{ "[{A}]":[{"[{B}]":3,"m":"C"}]}]
                isError = jsonStart && state == 0;//重复开始错误 同时不是值处理。
                break;
            case ‘}‘:
                isError = !jsonStart || (keyStart > -1 && state == 0);//重复结束错误 或者 提前结束。
                break;
            case ‘[‘:
                isError = arrayStart && state == 0;//重复开始错误
                break;
            case ‘]‘:
                isError = !arrayStart;//重复开始错误
                break;
            case ‘"‘:
            case ‘\‘‘:
                isError = !jsonStart;//未开始Json
                break;
            case ‘:‘:
                isError = !jsonStart || (jsonStart && keyStart < 2 && valueStart < 2 && state == 1);//未开始Json 同时 只能处理在取值之前。
                break;
            case ‘,‘:
                isError = (!jsonStart && !arrayStart) || (jsonStart && keyStart < 2 && valueStart < 2 && state == 0);//未开始Json 同时 只能处理在取值之后。
                break;
            default: //值开头。。
                isError = !jsonStart || (keyStart == 0 && valueStart == 0 && state == 0);//
                break;
        }
        //if (isError)
        //{

        //}
    }
}

2:实现代码(内部实现类):JsonSplit

PS:Log这个类的代码可以先注释屏蔽。

package cyq.data.tool;

import java.util.*;

import cyq.data.Log;

public class JsonSplit
{
    public static boolean IsJson(String json)
    {
        return IsJsonAndBackIndex(json)==-1;
    }
    public static int IsJsonAndBackIndex(String json)
    {
        if(json==null || json.isEmpty() || json.length()==1)
        {
            return 0;
        }

        if ((json.charAt(0) == ‘{‘ && json.charAt(json.length() - 1) == ‘}‘) ||
            (json.charAt(0)== ‘[‘ && json.charAt(json.length() - 1)== ‘]‘))
        {
            int errIndex = 0;
            CharState cs = new CharState();
            char c;
            for (int i = 0; i < json.length(); i++)
            {
                c = json.charAt(i);
                if (SetCharState(c, cs) && cs.childrenStart)//设置关键符号状态。
                {
                    String item = json.substring(i);
                    int[] v=GetValueLength(item, true);
                    int length = v[0];
                    int err=v[1];
                    cs.childrenStart = false;
                    if (err > 0)
                    {
                        errIndex = i + err;
                        return errIndex;
                    }
                    i = i + length - 1;
                }
                if (cs.isError)
                {
                    errIndex = i;
                    return errIndex;
                }
            }

            if( !cs.arrayStart && !cs.jsonStart)
            {
                return -1;
            }
            return errIndex;
        }
        else
        {
            return 0;
        }
    }
    static List<LinkedHashMap<String, String>> Split(String json)
    {
        List<LinkedHashMap<String, String>> result = new ArrayList<LinkedHashMap<String, String>>();

        if (json!=null && !json.isEmpty())
        {
            LinkedHashMap<String, String> dic = new LinkedHashMap<String, String>();
            String key = "";
            StringBuilder value = new StringBuilder();
            CharState cs = new CharState();
            try
            {
                //region 核心逻辑
                char c;
                for (int i = 0; i < json.length(); i++)
                {
                    c = json.charAt(i);
                    if (!SetCharState(c, cs))//设置关键符号状态。
                    {
                        if (cs.jsonStart)//Json进行中。。。
                        {
                            if (cs.keyStart > 0)
                            {
                                key += c;
                            }
                            else if (cs.valueStart > 0)
                            {
                                value.append(c);
                                //value += c;
                            }
                        }
                        else if (!cs.arrayStart)//json结束,又不是数组,则退出。
                        {
                            break;
                        }
                    }
                    else if (cs.childrenStart)//正常字符,值状态下。
                    {
                        String item = json.substring(i);
                        int[] v= GetValueLength(item, false);
                        int length =v[0];
                        //int temp=v[1];
                        //value = item.SubString(0, length);
                        value.setLength(0);
                        value.append(item.substring(0, length));
                        cs.childrenStart = false;
                        cs.valueStart = 0;
                        //cs.state = 0;
                        cs.setDicValue = true;
                        i = i + length - 1;
                    }
                    if (cs.setDicValue)//设置键值对。
                    {
                        if (key!=null && !key.isEmpty() && !dic.containsKey(key))
                        {
                            //if (value != String.Empty)
                            //{
                            boolean isNull = json.charAt(i - 5) == ‘:‘ && json.charAt(i) != ‘"‘ && value.length() == 4 && value.toString() == "null";
                            if (isNull)
                            {
                                value.setLength(0);
                            }
                            dic.put(key, value.toString());

                            //}
                        }
                        cs.setDicValue = false;
                        key = "";
                        value.setLength(0);
                    }

                    if (!cs.jsonStart && dic.size() > 0)
                    {
                        result.add(dic);
                        if (cs.arrayStart)//处理数组。
                        {
                            dic = new LinkedHashMap<String, String>();
                        }
                    }
                }
                //endregion

            }
            catch (Exception err)
            {
                Log.WriteLogToTxt(err);
            }
            finally
            {
                key = null;
                value.setLength(0);
                value = null;
            }
        }
        return result;
    }
    /// <summary>
    /// 获取值的长度(当Json值嵌套以"{"或"["开头时)
    /// </summary>
    private static int[] GetValueLength(String json, boolean breakOnErr)
    {

        int errIndex = 0;
        int len = 0;
        if (json!=null && !json.isEmpty())
        {
            CharState cs = new CharState();
            char c;
            for (int i = 0; i < json.length(); i++)
            {
                c = json.charAt(i);
                if (!SetCharState(c, cs))//设置关键符号状态。
                {
                    if (!cs.jsonStart && !cs.arrayStart)//json结束,又不是数组,则退出。
                    {
                        break;
                    }
                }
                else if (cs.childrenStart)//正常字符,值状态下。
                {
                    int[] v=GetValueLength(json.substring(i), breakOnErr);//递归子值,返回一个长度。。。
                    int length = v[0];
                    errIndex=v[1];
                    cs.childrenStart = false;
                    cs.valueStart = 0;
                    //cs.state = 0;
                    i = i + length - 1;
                }
                if (breakOnErr && cs.isError)
                {
                    errIndex = i;
                    break;
                }
                if (!cs.jsonStart && !cs.arrayStart)//记录当前结束位置。
                {
                    len = i + 1;//长度比索引+1
                    break;
                }
            }
        }
        int[] valueAndErrIndex=new int[2];
        valueAndErrIndex[0]=len;
        valueAndErrIndex[1]=errIndex;
        return valueAndErrIndex;
    }

    /// <summary>
    /// 设置字符状态(返回true则为关键词,返回false则当为普通字符处理)
    /// </summary>
    private static boolean SetCharState(char c, CharState cs)
    {
        switch (c)
        {
            case ‘{‘://[{ "[{A}]":[{"[{B}]":3,"m":"C"}]}]
                if (cs.keyStart <= 0 && cs.valueStart <= 0)
                {
                    cs.CheckIsError(c);
                    if (cs.jsonStart && cs.state == 1)
                    {
                        cs.valueStart = 0;
                        cs.childrenStart = true;
                    }
                    else
                    {
                        cs.state = 0;
                    }
                    cs.jsonStart = true;//开始。
                    return true;
                }
                break;
            case ‘}‘:

                if (cs.keyStart <= 0 && cs.valueStart < 2)
                {
                    cs.CheckIsError(c);
                    if (cs.jsonStart)
                    {
                        cs.jsonStart = false;//正常结束。
                        cs.valueStart = 0;
                        cs.setDicValue = true;
                    }
                    return true;
                }
                // cs.isError = !cs.jsonStart && cs.state == 0;

                break;
            case ‘[‘:

                if (!cs.jsonStart)
                {
                    cs.CheckIsError(c);
                    cs.arrayStart = true;
                    return true;
                }
                else if (cs.jsonStart && cs.state == 1 && cs.valueStart < 2)
                {
                    cs.CheckIsError(c);
                    //cs.valueStart = 1;
                    cs.childrenStart = true;
                    return true;
                }

                break;
            case ‘]‘:

                if (!cs.jsonStart && cs.keyStart <= 0 && cs.valueStart <= 0)
                {
                    cs.CheckIsError(c);
                    if (cs.arrayStart)// && !cs.childrenStart
                    {
                        cs.arrayStart = false;
                    }
                    return true;
                }

                break;
            case ‘"‘:
            case ‘\‘‘:
                cs.CheckIsError(c);

                if (cs.jsonStart)
                {
                    if (cs.state == 0)//key阶段
                    {
                        cs.keyStart = (cs.keyStart <= 0 ? (c == ‘"‘ ? 3 : 2) : 0);
                        return true;
                    }
                    else if (cs.state == 1)//值阶段
                    {
                        if (cs.valueStart <= 0)
                        {
                            cs.valueStart = (c == ‘"‘ ? 3 : 2);
                            return true;
                        }
                        else if ((cs.valueStart == 2 && c == ‘\‘‘) || (cs.valueStart == 3 && c == ‘"‘))
                        {
                            if (!cs.escapeChar)
                            {
                                cs.valueStart = 0;
                                return true;
                            }
                            else
                            {
                                cs.escapeChar = false;
                            }
                        }

                    }
                }

                break;
            case ‘:‘:
                cs.CheckIsError(c);

                if (cs.jsonStart && cs.keyStart < 2 && cs.valueStart < 2 && cs.state == 0)
                {
                    cs.keyStart = 0;
                    cs.state = 1;
                    return true;
                }
                // cs.isError = !cs.jsonStart || (cs.keyStart < 2 && cs.valueStart < 2 && cs.state == 1);

                break;
            case ‘,‘:
                cs.CheckIsError(c);

                if (cs.jsonStart && cs.keyStart < 2 && cs.valueStart < 2 && cs.state == 1)
                {
                    cs.state = 0;
                    cs.valueStart = 0;
                    cs.setDicValue = true;
                    return true;
                }
                else if (cs.arrayStart && !cs.jsonStart)
                {
                    return true;
                }
                break;
            case ‘ ‘:
            case ‘\r‘:
            case ‘\n‘:
                if (cs.jsonStart && cs.keyStart <= 0 && cs.valueStart <= 0)
                {
                    return true;//跳过空格。
                }
                break;
            default: //值开头。。
                cs.CheckIsError(c);
                if (c == ‘\\‘) //转义符号
                {
                    if (cs.escapeChar)
                    {
                        cs.escapeChar = false;
                    }
                    else
                    {
                        cs.escapeChar = true;
                        return true;
                    }
                }
                else
                {
                    cs.escapeChar = false;
                }
                if (cs.jsonStart)
                {
                    if (cs.keyStart <= 0 && cs.state <= 0)
                    {
                        cs.keyStart = 1;//无引号的
                    }
                    else if (cs.valueStart <= 0 && cs.state == 1)
                    {
                        cs.valueStart = 1;//无引号的
                    }
                }
                break;
        }
        return false;
    }

}

3:实现代码(外部调用类):JsonHelper

package cyq.data.tool;

import java.util.*;

public class JsonHelper {
     /// <summary>
    /// 检测是否Json格式的字符串
    /// </summary>
    /// <param name="json">要检测的字符串</param>
    public static boolean IsJson(String json)
    {
        return JsonSplit.IsJson(json);
    }

    /// <summary>
    /// 将Json分隔成键值对。
    /// </summary>
    public static Map<String, String> Split(String json)
    {
        List<LinkedHashMap<String, String>> result = JsonSplit.Split(json);
        if (result != null && result.size() > 0)
        {
            return result.get(0);
        }
        return null;
    }
    /// <summary>
    /// 将Json 数组分隔成多个键值对。
    /// </summary>
    public static List<LinkedHashMap<String, String>> SplitArray(String jsonArray)
    {
        if (jsonArray==null || jsonArray.isEmpty())
        {
            return null;
        }
        jsonArray = jsonArray.trim();
        return JsonSplit.Split(jsonArray);
    }
}

4:实现代码(单元测试类):JsonTest

PS:标签Key没用引号,所以识别是false,但Split方法是兼容不严格模式的,所以还能分成Map。

总结:

总体而言,虽然Java很原始,C#很高级,但技术这东西,走向一个极端后,也得学学大闸蟹,得横着走。

只有两手抓,两手都硬的时候,才不会被技术所孤立。。。

时间: 2024-10-04 17:24:03

识别Json字符串并分隔成Map集合的相关文章

Java版本:识别Json字符串并分隔成Map集合

前言: 最近又看了点Java的知识,于是想着把CYQ.Data V5迁移到Java版本. 过程发现坑很多,理论上看大部分很相似,实践上代码写起来发现大部分都要重新思考方案. 遇到的C#转Java的一些小问题: 1:C#的ref:这个参数的主要意图是: 就算方法内部重新对参数重新(new)赋值,也能保证外部的参数指向新的值. Java木有了,不知道新的方案是什么?还是说只能避免方法内部重新(new)赋值? 2:C#的out:这个参数的主要意图是: 处理多值返回的问题. Java木有了,只能改返回数

SpringMVC学习笔记001-服务器端获取JSON字符串并解析

一.服务器端获取JSON字符串并解析 方式一: 前端发送一个getJSONString.spring请求,后面加时间是为了保证浏览器每次都把它当做一个不同的请求,不调用浏览器缓存. 思路:利用JSON.stringify()把一个JS对象实例[object:object]转化为json格式的字符串.$.post()接受的可选参数data可以是plainObject/String 即key/value的键值对或者字符串. <script src="jquery-1.3.2.js"&

将xml字符串的所有叶标签转换成Map集合

实际问题:对方服务器接口采用webservice方式返回xml报文,现需解析xml获取所有叶节点的标签名及携带的值 解决方案:利用dom4j解析xml并利用递归获取叶节点,将标签名及标签值封装到Map集合供业务调用 import java.util.HashMap; import java.util.List; import java.util.Map; import org.dom4j.Document; import org.dom4j.DocumentHelper; import org.

菜鸟学习Spring——SpringMVC注解版在服务器端获取Json字符串并解析

一.概述. SpringMVC在服务端把客户端传过来的JSON字符串,并把JSON字符串转成 JSON对象并取得其中的属性值,这个在项目中经常用到. 二.代码演示. 需要添加的jar包. 2.1 web.xml. <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns=&

Android获取服务器Json字符串并显示在ListView上面

已经好久没有更新博客,今天终于有新的东西可以记录了. 通过这次的任务学习到了以前没有注意到的知识点,真的有种书读百遍,其义自见的感觉.这次又重新认识了<Handler消息机制原理>.这次的任务中有更新UI.但是忘记了在Android4.0以后不能在UI线程访问网络,子线程也不能更新UI界面.下面我来展示一下这次的效果图. 这次的任务是:获取服务器端的json字符串,并解析显示在Android界面上. 当我接到这个任务的时候,首先想到的是利用Fragment布局加上ListView布局.但是因为

java解析传过来的json字符串并以数组的方式保存

1.网上找了好多关于解析json放入数组的例子,但大多数都是提前写好的数组格式比如String str="[{name:'a',value:'aa'},{name:'b',value:'bb'},{name:'c',value:'cc'}]", 这样就把参数写死了,不是我想要的格式. 2.自己整理的name.value格式,定义了nameJson.valueJson变量..equals()括号里就是你代入的参数. 3.用到了阿里的fastJson工具,一定要添加相关的jar包,不然肯定

python解析json字符串并返回对象

import json from argparse import Namespace obj = json.loads(jsonData,object_hook=lambda d: Namespace(**d)) jsonData变量是json字符串 原文地址:https://www.cnblogs.com/codeDevotee/p/12205809.html

fastjson将json格式字符串转成list集合

1.gameListStr = "[{"gameId":"1","gameName":"哈哈"},{"gameId":"2","gameName":"呵呵"}]"; 2. List<Game> gameList = JSONObject.parseArray(gameListStr, Game.class); pub

json转换成list map集合

import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Set; import net.sf.json.JSONArray; import net.sf.json.JSONObject; public class JSONHelper { /** * 将JSONObjec对象转换成Map集合 * @see JSONHelper#reflect(JSONArray)