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'


JSON(全称为javascript Object Notation)
是一种轻量级的数据交换格式。它是基于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数据

在 C# 中,如何为具有多个嵌套数组的 JSON 对象建模?

如何在 C# 中创建嵌套(父子)JSON 响应?

C# json提取多层嵌套到数组

C#读取Excel中嵌套的Json对象,Json带斜杠的问题(其一)

java怎么组装多层嵌套json