原先一直做CS的开发,对Json了解不多,最近转做BS后,才接触到了Json。作为后台与前端页面数据交互的基础,Json的地位非常重要,自然而然Json转换方法的重要性也不言面喻。
最开始使用的是同事原来写好的对象转Json的方法,并没有什么问题,不过一次偶然的转换,让我发现这个方法的局限性。当时我尝试将一个包含List属性的对象转成Json,该对象的List属性中有若干个对象,本以为转出来的Json字符串会带着这个属性,同时带着List中的所有对象,可实际转换的结果却是该属性的值——Object。考虑到后面可能也会类似的情况要处理,我打算重写该方法一次性解决这个问题。不过粗略研究代码后却有些犯难,这部分代码涉及到反射和特性的知识,而我对这部分知识还不够了解,尝试了简单的改写后发现实现难度有些大,所以放弃了改写的想法。
既然改写难度大,那么是否可以使用C#自带类库中类和方法呢?抱着这个想法在网上搜到了使用System.Runtime.Serialization.Json命名空间中DataContractJsonSerializer类转换Json的方法。在测试中发现使用这种方法转换存在两个问题:第一,生成的Json字符串中,会将自动化属性包裹在<>k__BackingField的尖括号中,如属性”CreateTime”,转换后会变成”< CreateTime>k__BackingField”;第二,如果对象的属性中有时间类型,则会将该属性的值转换成\/Date(1409752544567+0800)\/类的格式,该格式中的数字是与1970年1月1日的毫秒数之差。解决第一个问题需要使用正则表达式查找替换,解决第二个问题不但需要正则表达式查找出那些数字,还要将其转换成时间。实现起来也很麻烦。
于是我又开始在网上寻找其他的解决方法,又发现使用System.Web.Script.Serialization命名空间下的JavaScriptSerializer也可以实现Json对象的互转。而且在测试中还发现使用这种方法不会将自动化属性被包裹在<>k__BackingField的尖括号中的问题,不过时间转换的问题依然存在。
如果C#自带类库中的类和方法无法方便的实现Json对象的互转,就只能求助于第三方类库了。JsonNet或说是NewtonSoft很快便吸引了我的注意。在测试的时候还出现了个小插曲,我使用从官方地址下载的压缩包中BIN目录下的Net4.0版本的库文件,在程序中执行到JsonConvert.SerializeObject方法的时候提示查找JsonConvert.cs文件。后来我打开源项目重新编译生成库文件后就能正常调用执行了。在测试中发现使用JsonConvert.SerializeObject默认的方法转换出来的Json字符串中,时间格式虽然不是我想要的,也属于格式化后的。接着继续在网上搜索是否有控制时间格式化的方法,终于找到了使用命名空间Newtonsoft.Json.Converters中的IsoDateTimeConverter类对象可以控制时间的格式化。另外测试了对象数组转Json和Json转对象及转对象数组的方法后,确认JsonNet适合使用。
另外在整理JsonNet实现代码的时候,意外发现了LitJson库,比较小巧,据说转换时的效率比较高。简单测试了一下发现它实现了时间默认格式的转换,不过不提供详细的控制,在这点上就不如JsonNet好。
个人感觉Json与对象的互转的技术实现关键在于反射和特性,待到有时间研究到这部分内容时再来深入分析、比较和学习。
以下收录了一些从网上找的解决对象与Json互转的方法,其中也包括处理时间格式化的几种方式,仅供备忘参考。
原文地址:http://blog.csdn.net/gaofang2009/article/details/6073029
主要类 |
命名空间 |
限制 |
内建LINQ支持 |
时间格式化支持 |
DataContractJsonSerializer |
System.Runtime.Serialization.Json |
通用 |
否 |
否 |
JavaScriptSerializer |
System.Web.Script.Serialization |
只能在Web环境使用 |
否 |
否 |
JsonArray、JsonObject、JsonValue |
System.Json |
只能在Silverlight中使用 |
是 |
未知 |
JsonConvert、JArray、JObject、JValue、JProperty |
Newtonsoft.Json |
通用 |
是 |
是 |
JsonMapper |
LitJson |
通用 |
未知 |
否 |
实体类:
usingSystem.Runtime.Serialization;
namespace WindowsFormsApplication1
{
[DataContract]
public class Person
{
[DataMember(Order= 0, IsRequired =true)]
public string Name { get; set; }
[DataMember(Order= 1)]
public int Age { get; set; }
[DataMember(Order= 2)]
public bool Alive { get; set; }
[DataMember(Order= 3)]
public string[] FavoriteFilms { get;set; }
[DataMember(Order= 4)]
public Person Child { get;set; }
}
}
定义:
Action<object> log = o =>Console.WriteLine(o);
Func<int,int, int> add = (x, y) => x + y;
var p1 = newPerson
{
Age = 12,
Alive = true,
Name = "lj",
FavoriteFilms = new[] {"Up","Avatar" }
};
var p2 = newPerson() { Age = 28, Name ="cy", Child = p1 };
帮助类:
// usingSystem.Runtime.Serialization.Json;
///
///解析JSON,仿Javascript风格
///
public static class JsonTool1
{
public static T parse
{
using(var ms =new MemoryStream(Encoding.UTF8.GetBytes(jsonString)))
{
return(T)newDataContractJsonSerializer(typeof(T)).ReadObject(ms);
}
}
public static stringstringify(object jsonObject)
{
using(var ms =new MemoryStream())
{
newDataContractJsonSerializer(jsonObject.GetType()).WriteObject(ms,jsonObject);
returnEncoding.UTF8.GetString(ms.ToArray());
}
}
}
用法:
// 序列化
var jsonString = JSON.stringify(new[] { p1, p2 });
log(jsonString == JSON.stringify(new List
log(jsonString);
// 反序列化,泛型集合
JSON.parse>(jsonString);
// 数组转换
JSON.parse
输出:
[{"Name":"lj","Age":12,"Alive":true,"FavoriteFilms":["Up","Avatar"],"Child":null
},{"Name":"cy","Age":28,"Alive":false,"FavoriteFilms":null,"Child":{"Name":"lj",
"Age":12,"Alive":true,"FavoriteFilms":["Up","Avatar"],"Child":null}}]
// using System.Web.Script.Serialization;
var jser = newJavaScriptSerializer();
var json = jser.Serialize(newList
var persons = jser.Deserialize>(json);
// using System.Json
var css = "{ /"#header/" :{background:/"red/"}, layout : [5,4,1],color:/"cyan/"}";
var style = JsonObject.Parse(css) as JsonObject;
(
from s in style
where s.Key == "color"
select (string)s.Value
).First().ToString();
// "cyan"
// 更多操作
style["layout"][0] = 22;
var hd = style["#header"];
style["body>div+p"] = hd;
style.Remove("#header");
var bd = new JsonObject();
bd["border"] = "1px solid cyan";
style["body>div+p"]["#meta"] = bd;
style.ToString();
//{"layout":[22,4,1],"color":"cyan","body>div+p":{"background":"red","#meta":{"border":"1pxsolid cyan"}}}
// using Newtonsoft.Json;
var json = JsonConvert.SerializeObject(new[] { p1, p2 });
var persons =JsonConvert.DeserializeObject>(json);
var ja = JArray.Parse(jsonString);
log(ja); //注意,格式化过的输出
输出:
[
{
"Name": "lj",
"Age": 12,
"Alive": true,
"FavoriteFilms": [
"Up",
"Avatar"
],
"Child": null
},
{
"Name": "cy",
"Age": 28,
"Alive": false,
"FavoriteFilms": null,
"Child": {
"Name": "lj",
"Age": 12,
"Alive": true,
"FavoriteFilms": [
"Up",
"Avatar"
],
"Child": null
}
}
]
LINQ:
var ageCount = ja.Select(j => (int)j["Age"]).Aggregate(add);
var q = from j in ja
where !j["Name"].Value
select (int)j["Age"];
log(q.Aggregate(add) == ageCount); //false
其他:
// 与Linq to XML 相似的嵌套构造函数:
var jo = new JObject(
newJProperty("age", persons.Select( p => p.Age)),
newJProperty("funny", true),
newJProperty("array", new JArray(new[] { 2, 4, 1 }))
);
log(jo);
// JObject 操作
var css = "{ /"#header/" :{background:/"red/"}, layout : [5,4,1] }";
var style = JObject.Parse(css);
var bd = new JObject();
bd["color"] = "1px solid cyan";
style["border"] = bd;
var hd = style["#header"];
style["body>div+p"] = hd;
hd.Parent.Remove();
style["layout"][0] = 22;
log(style);
输出:
{
"age": [
12,
28
],
"funny": true,
"array": [
2,
4,
1
]
}
{
"layout": [
22,
4,
1
],
"border": {
"color": "1px solid cyan"
},
"body>div+p": {
"background": "red"
}
}
来自:http://www.mzwu.com/article.asp?id=1913
参考文章地址:http://de.cel.blog.163.com/blog/static/514512362011214105533226/
///
///主要使用了Newtonsoft.Json使用了对象与Json字符串之间的互转
///
public class JsonToolEx
{
public static string ToJson(object obj,stringdateTimeFormat = "yyyy-MM-dd")
{
IsoDateTimeConvertertimeConverter =new IsoDateTimeConverter();
timeConverter.DateTimeFormat =dateTimeFormat;
returnJsonConvert.SerializeObject(obj,timeConverter);
}
public static T ToObject
{
returnJsonConvert.DeserializeObject
}
}
public class JsonToolLit
{
public static string ToJson(object obj)
{
returnJsonMapper.ToJson(obj);
}
public static T ToObject
{
returnJsonMapper.ToObject
}
}
原文地址:http://www.jb51.net/article/46456.htm
开发中有时候需要从服务器端返回json格式的数据,在后台代码中如果有DateTime类型的数据使用系统自带的工具类序列化后将得到一个很长的数字表示日期数据,如下所示:
复制代码代码如下:
//设置服务器响应的结果为纯文本格式
context.Response.ContentType = "text/plain";
//学生对象集合
List
{
new Student(){Name ="Tom",
Birthday=Convert.ToDateTime("2014-01-31 12:12:12")},
new Student(){Name="Rose",
Birthday=Convert.ToDateTime("2014-01-10 11:12:12")},
new Student(){Name="Mark",
Birthday=Convert.ToDateTime("2014-01-09 10:12:12")}
};
//javascript序列化器
JavaScriptSerializer jss=new JavaScriptSerializer();
//序列化学生集合对象得到json字符
string studentsJson=jss.Serialize(students);
//将字符串响应到客户端
context.Response.Write(studentsJson);
context.Response.End();
运行结果是:
其中Tom所对应生日“2014-01-31”变成了1391141532000,这其实是1970 年 1 月 1 日至今的毫秒数;1391141532000/1000/60/60/24/365=44.11年,44+1970=2014年,按这种方法可以得出年月日时分秒和毫秒。这种格式是一种可行的表示形式但不是普通人可以看懂的友好格式,怎么让这个格式变化?
解决办法:
using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Script.Serialization;
namespace JsonDate1
{
using System.Linq;
///
/// 学生类,测试用
///
public class Student
{
///
/// 姓名
///
public String Name { get; set; }
///
/// 生日
///
public DateTime Birthday { get; set; }
}
///
/// 返回学生集合的json字符
///
public class GetJson : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
//设置服务器响应的结果为纯文本格式
context.Response.ContentType = "text/plain";
//学生对象集合
List
{
new Student(){Name="Tom",Birthday =Convert.ToDateTime("2014-01-31 12:12:12")},
new Student(){Name="Rose",Birthday =Convert.ToDateTime("2014-01-1011:12:12")},
new Student(){Name="Mark",Birthday =Convert.ToDateTime("2014-01-0910:12:12")}
};
//使用Select方法重新投影对象集合将Birthday属性转换成一个新的属性
//注意属性变化后要重新命名,并立即执行
var studentSet =
students.Select
(
p => new { p.Name, Birthday= p.Birthday.ToString("yyyy-mm-dd") }
).ToList();
//javascript序列化器
JavaScriptSerializer jss = new JavaScriptSerializer();
//序列化学生集合对象得到json字符
string studentsJson = jss.Serialize(studentSet);
//将字符串响应到客户端
context.Response.Write(studentsJson);
context.Response.End();
}
public bool IsReusable
{
get
{
return false;
}
}
}
}
Select方法重新投影对象集合将Birthday属性转换成一个新的属性,注意属性变化后要重新命名,属性名可以相同;这里可以使用select方法也可以使用LINQ查询表达式,也可以选择别的方式达到相同的目的;这种办法可以将集合中客户端不用的属性剔除,达到简单优化性能的目的。
运行结果:
这时候的日期格式就已经变成友好格式了,不过在javascript中这只是一个字符串。
在javascript中将"Birthday":"\/Date(1391141532000)\/"中的字符串转换成javascript中的日期对象,可以将Birthday这个Key所对应的Value中的非数字字符以替换的方式删除,到到一个数字1391141532000,然后实例化一个Date对象,将1391141532000毫秒作为参数,得到一个javascript中的日期对象,代码如下:
$(function() {
$.getJSON("getJson.ashx", function (students) {
$.each(students, function(index, obj) {
$("
").html(obj.Name).appendTo("#ulStudents");
//使用正则表达式将生日属性中的非数字(\D)删除
//并把得到的毫秒数转换成数字类型
var birthdayMilliseconds =parseInt(obj.Birthday.replace(/\D/igm, ""));
//实例化一个新的日期格式,使用1970 年 1 月 1 日至今的毫秒数为参数
var birthday = newDate(birthdayMilliseconds);
$("
").html(birthday.toLocaleString()).appendTo("#ulStudents");;});
});
});