前言:

最近又看了点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. (原)java中opencv的width的问题

    调试程序,我这边负责在JNI中将缓冲区中的数据转换成bitmp.测试时用320*240的图像测试正常,但是别人使用的图像宽度为270时,图像出现了错位(没截图,不好理解). 首先想到的是opencv的 ...

  2. Eclipse运行Tomcat7源码

    1. 各环境版本: jdk1.6.0_45 (亲测jdk1.7.0_07会有问题,不要用1.7版本的) apache-ant-1.9.4 apache-tomcat-7.0.61-src 2. 安装a ...

  3. 从远程oracle上导入到本地同一张表中不存在的记录的方法

    场景:在远程oracle上存在一张表A,在本地同样存在一张相同表结构的表B.由于本地表B中保存了业务系统操作产生的几条记录,同时原来导入了A中的部分记录,但是并没有保存A中全部的记录.A中有15条记录 ...

  4. RecyclerView不同类型Item的展示

    代码如下: public class AccessoiresAdapter extends RecyclerView.Adapter { final int VIEW_TYPE_ACCESSORY = ...

  5. 第一章——Activity的生命周期

    问题总结: 1.Activity完整的生命周期 2.当打开第二个Activity并关闭时候的生命周期. ①.解释为什么onPause()方法不要有耗时操作 3.Activity发生异常重启的时候问题: ...

  6. AlertDialog与DialogFragment

    1.AlertDialog 作用:简单的弹出框实现 创建方法: AlertDialog alert = new AlertDialog.Builder(); 使用: new AlertDialog.B ...

  7. Javascript自定义类

    JavaScript并不是严格的面向对象的语言,但是带有面向对象的一些特性,我们可以通过这些特性创建js中的自定义类. JavaScript中的类其实是function关键字包裹的一系列变量和方法. ...

  8. python操作csv-xls完善后的代码

    #coding:utf-8 #导入相应模块 import csv,xlwt,sys,os,fnmatch,xlrd from xlutils.copy import copy #对xls文件中的绝对值 ...

  9. LINUX下QT与C语言通过网卡名获取网卡IP与MAC

    1.QT下 QString RuntimeConfig::ipAddress(QString network) { QList<QNetworkAddressEntry> list; QS ...

  10. 关于Thread的Runnable和Callable接口

    其实非常简单:其实他们的区别就是Callable有返回值并且可以抛出异常. /** * Represents a command that can be executed. Often used to ...