C#怎么取带嵌套的格式一致的JSON?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#怎么取带嵌套的格式一致的JSON?相关的知识,希望对你有一定的参考价值。
如题,获取到一个JSON字符串后,怎么分别获得字符串中的各项(及各种属性)?
我要获得ID1[URL:XXX;Filter:XXX;Size:XXX],ID2[URL:XXX;Filter:XXX;Size:XXX],ID3[ID4[URL:XXX;Filter:XXX;Size:XXX],ID5[URL:XXX;Filter:XXX;Size:XXX]]这样的形式,要能实现功能的代码!谢谢,下面是JSON块。
'ID1':
'URL':'XXXXXXX',
'Filter':'*.doc|*.docx',
'Size':'10240'
,
'ID2':
'URL':'YYYYYYY',
'Filter':'*.xls|*.xlsx',
'Size':'10240'
,
'ID3':
'ID4':
'URL':'ZZZZZZ',
'Filter':'*.txt',
'Size':'10240'
,
'ID5':
'URL':'ZZZZZZ',
'Filter':'*.txt',
'Size':'10240'
是一种轻量级的数据交换格式。它是基于JavaScript语法标准的一个子集。
JSON采用完全独立于语言的文本格式,可以很容易在各种网络、平台和程序之间传输。JSON的语法很简单,易于人阅读和编写,同时也易于机器解析和生
成。
JSON与XML的比较
◆可读性
JSON和XML的可读性相比较而言,由于XML提供辅助的标签,更加适合人阅读和理解。
◆文件大小与传输
XML允许使用方便的标签,所以文件尺寸是要比JSON大的。而且JSON源于Javascript,所以天生的主战场是Javascript与网络,在这里,JSON有着XML无法赶超的优势。
JSON语法
1. JSON 语法是 JavaScript 对象表示法语法的子集。
•数据在名称/值对中:名称是字符串,使用双引号表示。值可以是:数字(整数或浮点数),字符串(在双引号中),数组(在方括号中),对象(在花括号中),true/false/null。
•数据由逗号分隔:
•花括号保存对象:对象可以包含各种数据,包括数组。
•方括号保存数组:数字可以包含对象。
例如:
"employees": [
"firstName": "Bill",
"lastName": "Gates"
,
"firstName": "George",
"lastName": "Bush"
]
2. 如果JSON中含有转义字符,则需要转义。例如文件路径中需要使用"\\"而不是"\"。例如: "file":"C:\\a.txt"。
.NET操作JSON
JSON文件读入到内存中就是字符串,.NET操作JSON就是生成与解析JSON字符串。操作JSON通常有以下几种方式:
1. 原始方式:自己按照JSON的语法格式,写代码直接操作JSON字符串。如非必要,应该很少人会走这条路,从头再来的。
2. 通用方式:这种方式是使用开源的类库Newtonsoft.Json(下载地址http://json.codeplex.com/)。下载后加入工程就能用。通常可以使用JObject, JsonReader, JsonWriter处理。这种方式最通用,也最灵活,可以随时修改不爽的地方。
(1)使用JsonReader读Json字符串:
string jsonText = @"""input"" : ""value"", ""output"" : ""result""";
JsonReader reader = new JsonTextReader(new StringReader(jsonText));
while (reader.Read())
Console.WriteLine(reader.TokenType + "\t\t" + reader.ValueType + "\t\t" + reader.Value);
(2)使用JsonWriter写字符串:
StringWriter sw = new StringWriter();
JsonWriter writer = new JsonTextWriter(sw);
writer.WriteStartObject();
writer.WritePropertyName("input");
writer.WriteValue("value");
writer.WritePropertyName("output");
writer.WriteValue("result");
writer.WriteEndObject();
writer.Flush();
string jsonText = sw.GetStringBuilder().ToString();
Console.WriteLine(jsonText);
(3)使用JObject读写字符串:
JObject jo = JObject.Parse(jsonText);
string[] values = jo.Properties().Select(item => item.Value.ToString()).ToArray();
(4)使用JsonSerializer读写对象(基于JsonWriter与JsonReader):
Project p = new Project() Input = "stone", Output = "gold" ;
JsonSerializer serializer = new JsonSerializer();
StringWriter sw = new StringWriter();
serializer.Serialize(new JsonTextWriter(sw), p);
Console.WriteLine(sw.GetStringBuilder().ToString());
StringReader sr = new StringReader(@"""Input"":""stone"", ""Output"":""gold""");
Project p1 = (Project)serializer.Deserialize(new JsonTextReader(sr), typeof(Project));
Console.WriteLine(p1.Input + "=>" + p1.Output);
上面的代码都是基于下面这个Project类定义:
class Project
public string Input get; set;
public string Output get; set;
此外,如果上面的JsonTextReader等类编译不过的话,说明是我们自己修改过的类,换成你们自己的相关类就可以了,不影响使用。
3. 内置方式:使用.NET Framework 3.5/4.0中提供的System.Web.Script.Serialization命名空间下的JavaScriptSerializer类进行对象的序列化与反序列化,很直接。
Project p = new Project() Input = "stone", Output = "gold" ;
JavaScriptSerializer serializer = new JavaScriptSerializer();
var json = serializer.Serialize(p);
Console.WriteLine(json);
var p1 = serializer.Deserialize<Project>(json);
Console.WriteLine(p1.Input + "=>" + p1.Output);
Console.WriteLine(ReferenceEquals(p,p1));
注意:如果使用的是VS2010,则要求当前的工程的Target Framework要改成.Net Framework 4,不能使用Client
Profile。当然这个System.Web.Extensions.dll主要是Web使用的,直接在Console工程中用感觉有点浪费资源。
此外,从最后一句也可以看到,序列化与反序列化是深拷贝的一种典型的实现方式。
4. 契约方式:使用System.Runtime.Serialization.dll提供的DataContractJsonSerializer或者 JsonReaderWriterFactory实现。
Project p = new Project() Input = "stone", Output = "gold" ;
DataContractJsonSerializer serializer = new DataContractJsonSerializer(p.GetType());
string jsonText;
using (MemoryStream stream = new MemoryStream())
serializer.WriteObject(stream, p);
jsonText = Encoding.UTF8.GetString(stream.ToArray());
Console.WriteLine(jsonText);
using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(jsonText)))
DataContractJsonSerializer serializer1 = new DataContractJsonSerializer(typeof(Project));
Project p1 = (Project)serializer1.ReadObject(ms);
Console.WriteLine(p1.Input + "=>" + p1.Output);
这里要注意,这里的Project类和成员要加相关的Attribute:
[DataContract]
class Project
[DataMember]
public string Input get; set;
[DataMember]
public string Output get; set;
实用参考:
JSON验证工具:http://jsonlint.com/
JSON简明教程:http://www.w3school.com.cn/json/
Newtonsoft.Json类库下载:http://json.codeplex.com/ 参考技术A Web Service接口方法
[WebMethod]
public string Project(string paramaters)
return paramaters;
实现代码
public string Post(string methodName, string jsonParas)
string strURL = Url + "/" + methodName;
//创建一个HTTP请求
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(strURL);
//Post请求方式
request.Method = "POST";
//内容类型
request.ContentType = "application/x-www-form-urlencoded";
//设置参数,并进行URL编码
//虽然我们需要传递给服务器端的实际参数是JsonParas(格式:[\"UserID\":\"0206001\",\"UserName\":\"ceshi\"]),
//但是需要将该字符串参数构造成键值对的形式(注:"paramaters=[\"UserID\":\"0206001\",\"UserName\":\"ceshi\"]"),
//其中键paramaters为WebService接口函数的参数名,值为经过序列化的Json数据字符串
//最后将字符串参数进行Url编码
string paraUrlCoded = System.Web.HttpUtility.UrlEncode("paramaters");
paraUrlCoded += "=" + System.Web.HttpUtility.UrlEncode(jsonParas);
byte[] payload;
//将Json字符串转化为字节
payload = System.Text.Encoding.UTF8.GetBytes(paraUrlCoded);
//设置请求的ContentLength
request.ContentLength = payload.Length;
//发送请求,获得请求流
Stream writer;
try
writer = request.GetRequestStream();//获取用于写入请求数据的Stream对象
catch (Exception)
writer = null;
Console.Write("连接服务器失败!");
//将请求参数写入流
writer.Write(payload, 0, payload.Length);
writer.Close();//关闭请求流
String strValue = "";//strValue为http响应所返回的字符流
HttpWebResponse response;
try
//获得响应流
response = (HttpWebResponse)request.GetResponse();
catch (WebException ex)
response = ex.Response as HttpWebResponse;
Stream s = response.GetResponseStream();
//服务器端返回的是一个XML格式的字符串,XML的Content才是我们所需要的Json数据
XmlTextReader Reader = new XmlTextReader(s);
Reader.MoveToContent();
strValue = Reader.ReadInnerXml();//取出Content中的Json数据
Reader.Close();
s.Close();
return strValue;//返回Json数据
Url的格式样例:"http://59.68.29.106:8087/IFT_Project.asmx"
methodName参数就是"Project"
JsonParas就是使用C# JavaScriptSerializer将List<Object>类型的对象序列化之后得到的值,数据格式:[\"UserID\":\"0206001\",\"UserName\":\"ceshi\"],Json数据中的中括号代表由着多个对象集合序列化,花括号代表一个对象序列化得到的结果,花括号里面的内容使用键值对的方式展示,多个属性之间用逗号隔开,每个对象也用逗号隔开。
request.ContentType必须设置值,建议使用"application/x-www-form-urlencoded",设置其他值就很容易报服务器内部异常,使用这种方式服务接口方法返回的是xml格式的字符串
payload将请求参数转换成二进制来保存,此处一定要将“paramaters”加入其中,不然会报异常缺少参数,paramaters就是服务接口函数的参数名。函数中使用了URL编码,注意在编码的时候只需要将键和值进行编码,不要将中间的=进行编码,不然getResponse的时候会报异常。
request.ContentLength也是必须设置的值
在得到响应流之后Stream s = response.GetResponseStream();需要使用Reader来解析响应流,这个地方我使用的是XmlTextReader,因为我服务方法返回的是xml格式的字符串,其中Json数据在xml的Content中。在取出Json数据之后,再进行相应的反序列化即可得到对象。 参考技术B
引用Newtonsoft.Json.dll
首先,大家要明白什么是json,了解更多关于json方面资料大家可以点击https://www.ibm.com/developerworks/cn/web/wa-lo-json/ ,我在这里简单介绍下json:
JSON 即 JavaScript Object Natation,它是一种轻量级的数据交换格式,非常适合于服务器与 JavaScript 的交互。和 XML 一样,JSON 也是基于纯文本的数据格式。由于 JSON 天生是为 JavaScript 准备的,因此,JSON 的数据格式非常简单,您可以用 JSON 传输一个简单的 String,Number,Boolean,也可以传输一个数组,或者一个复杂的 Object 对象。
在.NET环境下面,我们使用Json.net来实现JSON数据的序列化和反序列化。
首先点击连接http://sourceforge.net/projects/csjson/?source=dlp 下载JSON .NET插件和代码。
然后在项目中进行引用Newtonsoft.Json.dll
添加命名空间:using Newtonsoft.Json;
下面介绍json序列化和反序列化的放个重要方法和例子:
JsonConvert.SerializeObject(object value)序列化,它有个重载方法JsonConvert.SerializeObject(object value, params JsonConverter[] converters)。
JsonConvert.DeserializeObject(string value, Type type),反序列化,它有个重载方法JsonConvert.DeserializeObject(string value, Type type, params JsonConverter[] converters)
这两个方法可以实现基本的序列化和反序列化要求,请看下面的例子:
首先我们先建一个Person类代码如下:
public class Person
private string name;
public string Name
get return name;
set name = value;
private int age;
public int Age
get return age;
set age = value;
1)序列化
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Newtonsoft.Json;
namespace JSONnet
public partial class test : System.Web.UI.Page
protected void Page_Load(object sender, EventArgs e)
Person person = new Person();
person.Name = "GoldenEasy";
person.Age = 25;
string strSerializeJSON = JsonConvert.SerializeObject(person);
Response.Write(strSerializeJSON);
输出结果:
"Name":"GoldenEasy","Age":25
2)反序列化
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Newtonsoft.Json;
namespace JSONnet
public partial class test : System.Web.UI.Page
protected void Page_Load(object sender, EventArgs e)
Person person = new Person();
person.Name = "GoldenEasy";
person.Age = 25;
string strSerializeJSON = JsonConvert.SerializeObject(person);
Person user = (Person)JsonConvert.DeserializeObject(strSerializeJSON, typeof(Person));
Response.Write(user.Name);
输出结果为:GoldenEasy
参考技术C Newtonsoft.Json序列化和反序列,
百度一下很多。
http://www.cnblogs.com/sbxwylt/archive/2008/12/31/1366199.html
不清楚可以详谈。 参考技术D DynamicJson
http://dynamicjson.codeplex.com/
封装好的json处理类库
C# - 将 json 格式的数据解析为嵌套的哈希表
【中文标题】C# - 将 json 格式的数据解析为嵌套的哈希表【英文标题】:C# - parsing json formatted data into nested hashtables 【发布时间】:2010-10-22 14:41:54 【问题描述】:我正在尝试在 C# 中处理一些 json 格式的数据,但是在确定解决问题的正确方法时遇到了一些问题。我的问题是 json 格式的数据将采用未知格式(我知道这听起来很奇怪……请继续阅读)。基本上,json 格式的数据将是一些名称/值对的集合,其中的值可能是也可能不是嵌套的名称/值对的数组。为了让事情更有趣,名称/值对数组的嵌套可以无限地继续下去。
例如: 我可能有一些数据看起来像……
"1":
"1.1":
"1.1.1": "value1",
"1.1.2": "value2",
"1.1.3": "value3"
,
"1.2": "value4",
"1.3":
"1.3.1":
"1.3.1.1": "value5",
"1.3.1.2": "value6"
,
"1.3.1.2": "value7",
"1.3.1.3": "value8"
不幸的是,我不知道会发生多少嵌套,从技术上讲,我不知道任何给定消息中会出现哪些名称/值对。
C# 中是否有任何受支持的机制可以让我轻松地将其解析为一组嵌套的 hastables?
我想做一些类似的事情(请注意,这段代码在语法上不是 100% 正确的,最好通过递归来完成……但它的想法很明确)。
Hashtable ht = [deserialize data method](jsonformattedstring);
foreach (Hashtable nested in ht)
If (nested.count > 1)
Foreach (hashtable next in nested)
…
【问题讨论】:
【参考方案1】:我不喜欢 .Net Json 解析...它偶尔会做一些奇怪的事情。我已经切换到Json.NET,一个开源库。它有一个很好的 JObject 对象,可以满足您的需要。
【讨论】:
JSON.NET 运行良好(在花费大量时间处理其复杂性之后)。我唯一的批评是 JObject、JValue 和其他“较低级别”的对象没有很好的文档记录。感谢您为我指明正确的方向。 我和伤寒在同一条船上。您有解决原始问题的任何代码示例吗?显然伤寒想通了,但我还没有。【参考方案2】:在 .NET 中,您有 JsonArray,它允许您加载和解析 JSON 数据。它创建了一个 JsonValue 数组,并基于它解析的 JSON 数据完全嵌套。
如果你特别需要 Hashtable,你可以翻译 JsonArray 中的数据,尽管 Hastable 几乎不赞成使用 Dictionary。
Josh Holmes 有一篇关于 .NET 中 JSON 的非常好的“入门”文章: http://www.joshholmes.com/blog/2009/01/20/PlayingWithJSON.aspx
【讨论】:
我认为它只能在 Silverlight 中使用。【参考方案3】:你可能想看看http://techblog.procurios.nl/k/n618/news/view/14605/14863/How-do-I-write-my-own-parser-for-JSON.html,它是一个简单的库,可以将 JSON 字符串解析为 Hashtables 和 ArrayLists。它还可以将这些结构再次转换为 JSON。
【讨论】:
这种原始的 C# 胜过承担依赖关系,或者与序列化类和迟钝的运行时结构混为一谈。如果您只想走一个结构,而不需要类的行为,那么这是您最好的解决方案。【参考方案4】:这是我用 C# 编写的用于解析 JSON 并返回字典的方法。当然,它并不适用于所有用例,但这样的事情会给你一个很好的 JSON 一次性解析:
/*
* This method takes in JSON in the form returned by javascript's
* JSON.stringify(Object) and returns a string->string dictionary.
* This method may be of use when the format of the json is unknown.
* You can modify the delimiters, etc pretty easily in the source
* (sorry I didn't abstract it--I have a very specific use).
*/
public static Dictionary<string, string> jsonParse(string rawjson)
Dictionary<string, string> outdict = new Dictionary<string, string>();
StringBuilder keybufferbuilder = new StringBuilder();
StringBuilder valuebufferbuilder = new StringBuilder();
StringReader bufferreader = new StringReader(rawjson);
int s = 0;
bool reading = false;
bool inside_string = false;
bool reading_value = false;
//break at end (returns -1)
while (s >= 0)
s = bufferreader.Read();
//opening of json
if (!reading)
if ((char)s == '' && !inside_string && !reading) reading = true;
continue;
else
//if we find a quote and we are not yet inside a string, advance and get inside
if (!inside_string)
//read past the quote
if ((char)s == '\"') inside_string = true;
continue;
if (inside_string)
//if we reached the end of the string
if ((char)s == '\"')
inside_string = false;
s = bufferreader.Read(); //advance pointer
if ((char)s == ':')
reading_value = true;
continue;
if (reading_value && (char)s == ',')
//we know we just ended the line, so put itin our dictionary
if (!outdict.ContainsKey(keybufferbuilder.ToString())) outdict.Add(keybufferbuilder.ToString(), valuebufferbuilder.ToString());
//and clear the buffers
keybufferbuilder.Clear();
valuebufferbuilder.Clear();
reading_value = false;
if (reading_value && (char)s == '')
//we know we just ended the line, so put itin our dictionary
if (!outdict.ContainsKey(keybufferbuilder.ToString())) outdict.Add(keybufferbuilder.ToString(), valuebufferbuilder.ToString());
//and clear the buffers
keybufferbuilder.Clear();
valuebufferbuilder.Clear();
reading_value = false;
reading = false;
break;
else
if (reading_value)
valuebufferbuilder.Append((char)s);
continue;
else
keybufferbuilder.Append((char)s);
continue;
else
switch ((char)s)
case ':':
reading_value = true;
break;
default:
if (reading_value)
valuebufferbuilder.Append((char)s);
else
keybufferbuilder.Append((char)s);
break;
return outdict;
【讨论】:
以上是关于C#怎么取带嵌套的格式一致的JSON?的主要内容,如果未能解决你的问题,请参考以下文章
在 C# 中,如何为具有多个嵌套数组的 JSON 对象建模?