前言:

最近又看了点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. C语言--关键字、标识(zhi)符、注释

    一.关键字 1. 关键字 是C语言中提供的有特殊含义的符号,同时也叫做保留字,在C语言中关键字一共有32个,它们分别被赋予了特殊的含义.如:main.int.struct等等. 2. 关键字的特征 1 ...

  2. MYSQL while 、repeat

    前期准备: createt table employee(ID int ,Name varchar(4)); 用下列方法向表中循环插入数据. ----------------------------- ...

  3. SQL Server sp_configure 控制内存使用

    背景知识: sp_configure   显示或更改当前服务器的全局配置设置(使用 sp_configure 可以显示或更改服务器级别的设置.) 查看 全局配置值 方法 1.execute sp_co ...

  4. 实现Linux下的U盘(USB Mass Storage)驱动

    如何实现Linux下的U盘(USB Mass Storage)驱动 版本:v0.7 How to Write Linux USB MSC (Mass Storage Class) Driver Cri ...

  5. 一道C语言面试题:得到整数的M进制表示字符串

    题目:输入整数n和M,输出n在M进制下的表示字符串.如n=3000,M=16,输出16进制下3000的表示字符串,为“BB8” 来源:某500强企业面试题目 思路:对n取模M,将得到的数字压入栈中,再 ...

  6. 一次rman恢复的实验

    本文主要针对备份和恢复数据文件,具体rman知识点查阅我的另一篇文章:http://blog.csdn.net/perfect_db/article/details/8765022 首先看看数据文件的 ...

  7. 电子科大POJ "a^b"

    a ^ b Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) C-sources: ...

  8. PHP实现好友生日邮件提醒

    我有一个想法是这样的,希望每天知道今天是我哪位好友的生日? 当然,我得首先保存我所有好友的生日信息 实现:在新浪申请免费服务器,并申请Mysql应用,然后建一张表保存好友的信息 我想,我已经完成第一步 ...

  9. HDU 3081Marriage Match II(二分法+并检查集合+网络流量的最大流量)

    职务地址:http://acm.hdu.edu.cn/showproblem.php? pid=3081 有一段时间没写最大流的题了,这题建图竟然想了好长时间... 刚開始是按着终于的最大流即是做多轮 ...

  10. 创建和使用RMAN存储脚本

    创建和使用RMAN存储脚本:1.连接恢复目录(可以不连接到目标库):C:\Users\Administrator>rman target sys/rusky@rusky catalog=rcat ...