前言:

最近又看了点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#很高级,但技术这东西,走向一个极端后,也得学学大闸蟹,得横着走。

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

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

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

    前言: 最近又看了点Java的知识,于是想着把CYQ.Data V5迁移到Java版本. 过程发现坑很多,理论上看大部分很相似,实践上代码写起来发现大部分都要重新思考方案. 遇到的C#转Java的一些 ...

  2. java把类似a=1&b=2&c=3的String类型数据转成map集合

    public static Map<String, Object> transStringToMap(String mapString, String separator, String ...

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

    实际问题:对方服务器接口采用webservice方式返回xml报文,现需解析xml获取所有叶节点的标签名及携带的值 解决方案:利用dom4j解析xml并利用递归获取叶节点,将标签名及标签值封装到Map ...

  4. java对象转化为json字符串并传到前台

    package cc.util; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import ...

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

    一.概述. SpringMVC在服务端把客户端传过来的JSON字符串,并把JSON字符串转成 JSON对象并取得其中的属性值,这个在项目中经常用到. 二.代码演示. 需要添加的jar包. 2.1 we ...

  6. asp.net用sql数据库生成json字符串并显示出来

    use Shop ,) )) insert into DictBase select '包装' UNION ALL select '价格' UNION ALL select '品牌' 工厂方法模式 I ...

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

    已经好久没有更新博客,今天终于有新的东西可以记录了. 通过这次的任务学习到了以前没有注意到的知识点,真的有种书读百遍,其义自见的感觉.这次又重新认识了<Handler消息机制原理>.这次的 ...

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

    1.gameListStr = "[{"gameId":"1","gameName":"哈哈"},{" ...

  9. json转换成list map集合

    import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Set; i ...

随机推荐

  1. google visit

    http://emuch.net/bbs/viewthread.php?tid=7630684&fpage=3&target=blank 内Facebook,twitter,dropb ...

  2. c#中override重写和new隐藏

    最近学习c#,昨晚看书看到多态.由于个人本身是从事java开发,于是拿来做对比便是自然的. 进入主题吧. c#中,子类要重写基类的方法,必须要基类声明中带有virtual关键字方法或者带有abstra ...

  3. MySQL的基本数据类型与数据类型优化

    1.选择优化的数据类型的标准 1)更小的通常更好. 一般情况下,应该尽量使用可以正确存储数据的最小数据类型.更小的数据类型通常更快,因为他们占用更少的磁盘.内存和CPU缓存,并且处理时需要的CPU周期 ...

  4. ListView的使用——聊天窗口

    一.步骤 1.在layout创建两个布局,分别是自己的回答条,和对方的回答条. 2.创建ChatMessage这个类,成员变量有头像地址.聊天内容.所属类型(假设1表示对方,2表示自己). 3.创建C ...

  5. python socket 编程之三:长连接、短连接以及心跳

    长连接:开启一个socket连接,收发完数据后,不立刻关闭连接,可以多次收发数据包. 短连接:开启一个socket连接,收发完数据后,立刻关闭连接. 心跳:长连接在没有数据通信时,定时发送数据包(心跳 ...

  6. CURL 和LIBCURL C++代码 上传本地文件,好不容易碰到了这种折腾我几天的代码

    解决了什么问题:curl在使用各种方式上传文件到服务器.一般的文件上传是通过html表单进行的,通过CURL可以不经过浏览器,直接在服务器端模拟进行表单提交,完成POST数据.文件上传等功能. 服务器 ...

  7. C++利用指针突破私有成员访问限制

    C++ 面向对象的一大特性就是封装,使用不同的访问控制符来控制外接对其的访问权限.比如: 1 class A 2 { 3 public: 4 A(): i(10){} 5 void print(){ ...

  8. hdr_beg(host) 主机名开始

    What does "acl cdn_name hdr_beg(host) -i foor.bar.com" mean in HAProxy's configuration? 在H ...

  9. 图数据库之Pregel

    /* 版权声明:能够随意转载,转载时请务必标明文章原始出处和作者信息 .*/            author: 张俊林 节选自<大数据日知录:架构与算法>十四章.书籍文件夹在此 Pre ...

  10. Codeforces Round #156 (Div. 2)---A. Greg&#39;s Workout

    Greg's Workout time limit per test 2 seconds memory limit per test 256 megabytes input standard inpu ...