前言:

最近又看了点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. volatile 和const 变量的使用

    一.volatile定义: 一个定义为volatile的变量是说这变量可能会被意想不到的被改变,这样,有了volatile变量后,就提醒编译器就不会去假设这个变量的值了.精确地说就是,编译中的优化器在 ...

  2. xml 文件的增删改查

    序列化和反序列化helper using System; using System.Collections.Generic; using System.Linq; using System.Text; ...

  3. JQuery中如何动态修改input的type属性

    代码如下: jQuery(".member_id").focus(function() { jQuery(this).val(''); }).blur(function() { i ...

  4. Scrapy安装问题

    按照说明直接使用pip install scrapy会有两个问题: fatal error: 'ffi.h' file not found fatal error: 'libxml/xmlversio ...

  5. jQuery插件jqplot的详细配置说明和渲染器

    jQuery插件jqplot的详细配置说明和渲染器 (2012-08-23 08:57:42) 转载▼ 标签: jqplot 详细配置 渲染器 it 分类: 技术类 jQuery.jqplot插件的官 ...

  6. 为什么开发人员对于PHP语言褒贬不一

    PHP 语言,作为服务器端开发的脚本语言,在网站开发方面非常有名.从1995年 Rasmus Lerdorf 创建之后,W3Techs 的调查显示在已知的服务端编程语言中,PHP 占了82%.其中不乏 ...

  7. Nginx 变量漫谈(五)

    前面在 (二) 中我们已经了解到变量值容器的生命期是与请求绑定的,但是我当时有意避开了“请求”的正式定义.大家应当一直默认这里的“请求”都是指客户端发起的 HTTP 请求.其实在 Nginx 世界里有 ...

  8. linux之模拟简单登录的脚本

    脚本如下: 运行结果:

  9. 一个简单java爬虫爬取网页中邮箱并保存

    此代码为一十分简单网络爬虫,仅供娱乐之用. java代码如下: package tool; import java.io.BufferedReader; import java.io.File; im ...

  10. MarkDown基础使用教程-by sixleaves

    以下是个人浏览文档,结合自己平时使用所总结, 和引用国外关于如何使用markdown的教程.如有不足,还请海涵,期待于您的交流.我觉得使用markdown书写挺好的! 工具下载,可以去下载gitboo ...