经常采集数据,肯定会碰到解析字符串,包括整个页面的html,或者json以及一些不标准的json格式。。。

以前用json序列化,有时候需要实体类,有的时候没有,比较麻烦,听说可以用JsonMapper,解析为字典格式。不过没用过,习惯了用最原始的方法来解析字符串,所以这里分享几个解析的案例。也许会有点作用。

解析字符串最常用的应该是Splite和Replace了。分割,然后替换一些引号之类的。最后组合。特别是采集的时候,经常会把html页面中某一段要提取出来,可能很多人用正则表达式,可是不会啊,也不愿意去学。那只好用这些原始的方法了,时间久了,也积累一些经验或者函数。看看几个例子。

1.不规则非json字符串

先看看这个例子,字符串是连在一起,没有换行的,为了方便观察,换行了,程序是原始在一起的:

[11101630,1532,14,'0','0',3,'2015,4,23,16,05,48','4',1,2,0,0],
[11101631,1532,14,'0','0',3,'2015,4,23,16,09,48','0',,,0,0],
[11101632,1532,14,'0','0',3,'2015,4,23,16,03,10','1',2,2,0,0]

先来分析一下这个字符串的特点,才能找到思路哦:

1.每一组数据都是在[]括号对中,每一组数据用,号分割,所以最终要形成一个数组来访问哦。

2.每一组的数据基本都是用 , 号分割,字符串类型还有单引号 ;

3.第7个数组是一个整体,也使用,号分割,整体是字符串有引号;

4.第2组数据有空值,直接用,号分割,所以splite的时候不能去掉空值,否则数组长度不一样,定位就乱了。

既然分析都完了,那思路呢?

1.组直接分割使用  ], 标记,然后每一组要Repalce掉 [  和 ] 。主要是最前和最后;

2.组内分割,使用  ,号标记分割,出来之前要把单引号给 替换掉 ;不然也是作为字符串,引号也包括进去了;

3.至于那个 数组 的处理,不能过于想复杂,分割之后,直接在最后增加1个元素,将固定位置7-12的组合起来;这样也许方便点;

4.由于空值有占位,所以每一组的长度是固定的。所以处理的时候直接根据自己想要的位置来组合。

下面看看代码了,C#版本,相对与一行代码,仔细看,Linq很是一个神器,真的是神奇。。。说多了都是泪,为啥就没早点学呢:

String str = @"[11101630,1532,14,'0','0',3,'2015,4,23,16,05,48','4',1,2,0,0],[11101631,1532,14,'0','0',3,'2015,4,23,16,09,48','0',,,0,0],[11101632,1532,14,'0','0',3,'2015,4,23,16,03,10','1',2,2,0,0]";

var result = str.Split(new string[] { "]," }, StringSplitOptions.None)  //先整体分割组
.Select(n => n.Replace("[", "")  //以下是组内分割,并去掉其他干扰字符
.Replace("]", "")
.Replace("\'", "")
.Split(',').ToList())
.Select(n =>     //对中间一个整体单独提取,进行组合,单独增加一个元素
{
n.Add(String.Format("{0},{1},{2},{3},{4},{5}", n[6], n[7], n[8], n[9], n[10], n[11]));return n;
}).ToList();

看看结果怎么样:

2.键值对字符串分割函数

  由于json数据格式都是键值对字符串,所以这里特意分享一个经常用到的分割函数,不用Json组件,那就用简单的方法做一个。这个函数来源于Newlife.Core,是X组件的重要部分。源码部分不过多解释,就是按规则将键值对直接分割保持在字典中,使用方法大家可以自己实验一下,或者参考下面的案例,都有用到这个方法。代码如下,为了方便使用,写成了扩展方法:

public static class StringHelper
{
/// <summary>拆分字符串成为名值字典</summary>
/// <param name="str">要分割字符串的</param>
/// <param name="nameValueSeparator">键值对的分隔符</param>
/// <param name="separators">分割字符</param>
/// <returns>键值对字典</returns>
public static IDictionary<String, String> SplitAsDictionary(this String str, String nameValueSeparator = "=", params String[] separators)
{
var dic = new Dictionary<String, String>();
if (String.IsNullOrWhiteSpace(str)) return dic; if (String.IsNullOrEmpty(nameValueSeparator)) nameValueSeparator = "=";
if (separators == null || separators.Length < 1) separators = new String[] { ",", ";" }; String[] ss = str.Split(separators, StringSplitOptions.RemoveEmptyEntries);
if (ss == null || ss.Length < 1) return null; foreach (var item in ss)
{
Int32 p = item.IndexOf(nameValueSeparator);
// 在前后都不行
if (p <= 0 || p >= item.Length - 1) continue; String key = item.Substring(0, p).Trim();
dic[key] = item.Substring(p + nameValueSeparator.Length).Trim();
} return dic;
}
}

上面默认的键值对分割符号为 = 号,根据实际情况进行修改,json格式里面一般是:冒号比较多。

3.复杂Json格式的字符串

上面的例子比较简单,这次看一个稍微复杂点的,虽然可能用JsonMapper可以很轻易做到,但试一下最原始的方法吧。还是按照上面的思路,先分析字符串的特点:字符串是连在一起,没有换行的,为了方便观察,换行了,程序是原始在一起的:

{1074:['墨聯','墨联','MEX D1','#098000','98'],
 2100:['美乙','美乙','USL D2','#E89B10','98'],
 1024:['阿甲','阿甲','ARG','#00CCFF','98'],
 1052:['哥倫甲','哥伦甲','COLCMA','#888500','98'],
 1028:['K聯賽','K联赛','KORL','#F75000','98'],
 1297:['球會友誼','球会友谊','CF','#5691D8','98'],
 2085:['奧女甲','奧女甲','AFB','#D86220','97']}

还是先分析特点,这个格式应该是json类似的了,比较规则:

  1. 组与之间是使用 , 号分割;前后有{}括号对;观察前后可以使用 ], 字符串将组分开;

  2. 键 是整数,键值是通过 : 号分割;

  3. 值是一个数组,有5个元素,通过 , 号分割

  4. 都有单引号,需要过滤掉;其他没有特殊情况;

代码解决过程:

string text = @"{1074:['墨聯','墨联','MEX D1','#098000','98'],2100:['美乙','美乙','USL D2','#E89B10','98'],1024:['阿甲','阿甲','ARG','#00CCFF','98'],1052:['哥倫甲','哥伦甲','COLCMA','#888500','98'],1028:['K聯賽','K联赛','KORL','#F75000','98'],1297:['球會友誼','球会友谊','CF','#5691D8','98'],2085:['奧女甲','奧女甲','AFB','#D86220','97']}";
var dic = text.Replace("\'", "").Split(new String[]{"],"}, StringSplitOptions.None) //先组分割
  .Select(n => n.Replace("{", "").Replace("}", "") //将组里面的干扰字符过滤掉
.Replace("[", "").Replace("]", "")
  .SplitAsDictionary(":", "\"") //键值对处理,冒号分隔符
  .ToDictionary(t => t.Key, t => t.Value.Split(',')//值再次进行分割,形成数组
  )).ToArray();

看看结果如何:

4.标准的json格式

在实际的采集过,可能会碰到直接url,返回的就是json格式,比较标准。这里举个例子,如下面这个页面链接:

http://d.dacai.com/zhishu/CorrectCorp.html?matchId=1899040&matchStatusId=41

点击开后,是这个样子:

这个应该够复杂了,我们分析一下,篇幅较大,源码对照链接:

  1. 每一大组数据,是用,号分割;整体也是前后大括号对{},有4个大类,键分布是:IndBodans,IndEvenGoals,IndGoalss,IndHalfFulls。

  2. 每一组的子类中,包括的都是同一个类型的数据,每一个子数据组都有N多个小的键值对,如MatchId,CorpId等等,使用},可以分割

    分析完成之后如何解决,思路是类似的,先整体分割,使用},进行,然后每一个之类作为键,对值再次进行分割。。。形成字典列表。其中的引号也是需要过滤的,至于数值类型,实际用到那个的时候,都是根据key去找,再进行Convert转换就可以了。看看源代码:

var dicList = doc.Split("{\"IndBodans\":[", "],\"IndEvenGoals\":[", //大类分割
"],\"IndGoalss\":[", "],\"IndHalfFulls\":[", "]}")
.Select(n => n.Replace("\"", "").Split("},{")//对每个大类处理,先过滤,再分割为子类
   .Select(k => k.Replace("{", "").Replace("}", "")//对子类过滤
                  .SplitAsDictionary(":", ","))//提取子类的键值对
  .ToArray()
).ToList();//列表

看看解析的结果如何:

注意,有元素是空值的,可以不用管。至于那几个键值对数组,最终属于哪一个大类?虽然没有直接标记出来,但是这个问题随便加一个判断就可以了,因为每一个类别的键名称是不一样的,看看是否包括对应的键就可以确定类别。

5.总结

虽然过程很简单,也许有更简单的办好,直接和实体类映射,json反序列化更方便,但有时候没有实体类,也挺麻烦。特别是这种变态复杂的,jsonmap直接处理不知道行不行。总之本文的目的是尽可能使用简单原始的方法来解决问题,也是一个思路。虽然有时候我很懒,喜欢用开源组件,但有的时候一旦用上原始的了,也不喜欢改了。

字符串分析处理的过程虽然繁琐,但基本都是比较简单的,细致一点,都不是事。

 最后把这个测试的源代码发上来,大家别忘了点赞哦。。。

  源代码:SpliteAsDictionaryDemo.rar

用原始方法解析复杂字符串,json一定要用JsonMapper么?的更多相关文章

  1. JAVA代码解析String字符串(json格式的)

    java解析String字符串(json格式) 需要jar包:json-lib-2.4-jdk15.jar 一. String str = "{\"name\":\&qu ...

  2. 【转】Jquery ajax方法解析返回的json数据

    转自http://blog.csdn.net/haiqiao_2010/article/details/12653555 最近在用jQuery的ajax方法传递接收json数据时发现一个问题,那就是返 ...

  3. c# json数据解析——将字符串json格式数据转换成对象

    网络中数据传输经常是xml或者json,现在做的一个项目之前调其他系统接口都是返回的xml格式,刚刚遇到一个返回json格式数据的接口,通过例子由易到难总结一下处理过程,希望能帮到和我一样开始不会的朋 ...

  4. c# json数据解析——将字符串json格式数据转换成对象或实体类

    网络中数据传输经常是xml或者json,现在做的一个项目之前调其他系统接口都是返回的xml格式,刚刚遇到一个返回json格式数据的接口,通过例子由易到难总结一下处理过程,希望能帮到和我一样开始不会的朋 ...

  5. JSON.parse() 方法解析一个JSON字符串

    JSON.parse() 方法解析一个JSON字符串,构造由字符串描述的JavaScript值或对象.可以提供可选的reviver函数以在返回之前对所得到的对象执行变换. 语法EDIT JSON.pa ...

  6. C#字符串数组排序 C#排序算法大全 C#字符串比较方法 一个.NET通用JSON解析/构建类的实现(c#) C#处理Json文件 asp.net使用Jquery+iframe传值问题

    C#字符串数组排序   //排序只带字符的数组,不带数字的 private   string[]   aa   ={ "a ", "c ", "b & ...

  7. js 将json字符串转换为json对象的方法解析-转

    例如: JSON字符串:var str1 = '{ "name": "cxh", "sex": "man" }'; JS ...

  8. js 将json字符串转换为json对象的方法解析

    推荐: var obj = eval('(' + str + ')'); var last=JSON.stringify(obj); //将JSON对象转化为string字符 例如: JSON字符串: ...

  9. javaScript 将json字符串转换为json对象的方法解析

    JSON字符串: var str1 = '{ "name": "cxh", "sex": "man" }'; JSON对 ...

随机推荐

  1. Online Judge(OJ)搭建(第一版)

    搭建 OJ 需要的知识(重要性排序): Java SE(Basic Knowledge, String, FileWriter, JavaCompiler, URLClassLoader, Secur ...

  2. ASP.NET Aries 入门开发教程8:树型列表及自定义右键菜单

    前言: 前面几篇重点都在讲普通列表的相关操作. 本篇主要讲树型列表的操作. 框架在设计时,已经把树型列表和普通列表全面统一了操作,用法几乎是一致的. 下面介绍一些差距化的内容: 1:树型列表绑定: v ...

  3. 第一个shell脚本

    打开文本编辑器,新建一个文件,扩展名为sh(sh代表shell),扩展名并不影响脚本执行,见名知意就好. #!/bin/bash echo "Hello World !" &quo ...

  4. 谈谈一些有趣的CSS题目(八)-- 纯CSS的导航栏Tab切换方案

    开本系列,谈谈一些有趣的 CSS 题目,题目类型天马行空,想到什么说什么,不仅为了拓宽一下解决问题的思路,更涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题 ...

  5. WPF 捕获键盘输入事件

    最近修改的一个需求要求捕获键盘输入的 Text,包括各种标点符号. 最开始想到的是 PreviewKeyDown 或者 PreviewKeyUp 这样的键盘事件. 但是这两个事件的对象 KeyEven ...

  6. 【转】外部应用和drools-wb6.1集成解决方案

    一.手把手教你集成外部应用和drools workbench6.1 1.         首先按照官方文档安装workbench ,我用的是最完整版的jbpm6-console的平台系统,里面既包含j ...

  7. Mysql基础代码(不断完善中)

    Mysql基础代码,不断完善中~ /* 启动MySQL */ net start mysql /* 连接与断开服务器 */ mysql -h 地址 -P 端口 -u 用户名 -p 密码 /* 跳过权限 ...

  8. Lind.DDD.Aspects通过Plugins实现方法的动态拦截~Lind里的AOP

    回到目录 .Net MVC之所以发展的如些之好,一个很重要原因就是它公开了一组AOP的过滤器,即使用这些过滤器可以方便的拦截controller里的action,并注入我们自己的代码逻辑,向全局的异常 ...

  9. 3种web会话管理的方式

    http是无状态的,一次请求结束,连接断开,下次服务器再收到请求,它就不知道这个请求是哪个用户发过来的.当然它知道是哪个客户端地址发过来的,但是对于我们的应用来说,我们是靠用户来管理,而不是靠客户端. ...

  10. iOS之延时执行(睡眠)的几种方法

    1. 最直接的方法: [self performSelector:@selector(deleyMethod) withObject:nil afterDelay:1.0]; 此方式要求必须在主线程中 ...