原文 Json.Net系列教程 2.Net类型与JSON的映射关系

首先谢谢大家的支持和关注.本章主要介绍.Net类型与JSON是如何映射的.我们知道JSON中类型基本上有三种:值类型,数组和对象.而.Net中的类型比较多.到底它们是如何映射的呢?

总体来讲,Json.Net将.Net中的基本类型(int,float,string等)转换为Json的值,数组和集合转换为Json的数组,其它转换为Json对象.

1.基本类型:

2.复杂类型:

3.注意
3.1数组和集合

如果你自定义了实现了数组和集合的类,并为类添加了自己的属性,抱歉在序列化时,该属性不会被序列化.例如我定义了如下的集合:

    public class MyArray : ArrayList
{
public string Name { get; set; }
}

实例化该类并序列化

            MyArray ma = new MyArray { Name = "myArray" };
ma.Add();
ma.Add();
ma.Add();
string json = JsonConvert.SerializeObject(ma);
Console.WriteLine(json);

效果:

如果我想把数组以对象的形式序列化,可不可以呢?答案是肯定的!
只要在定义的数组类的前面加上特性"JsonObject"即可,当然先要引入命名空间"Newtonsoft.Json".

    [JsonObject]
public class MyArray : ArrayList
{
public string Name { get; set; }
}

结果:

是的,你会发现结果中没有我们添加的值了,并且多出了很多其他我们并没有定义的值,这是因为我们添加的值在ArrayList中是以私有数组来存储的,默认情况下,Json.Net是仅仅序列化公有成员的.多出来的值是继承的接口中的属性.

3.2字典类型

字典类型(Dictionary,IDictionary,Hashtable等)会被序列化为对象,是以其中的key/value的形式来序列化,额外添加的属性不会被序列化.这里不再详讲了.

3.3Dynamic类型

在.Net4.0中,Dynamic基本上有两种用法.
一种是作为属性来用,在这种情况下序列化时会根据实际的类型来序列化.
第二
种用法是继承了IDynamicMetaObjectProvider 接口或者DynamicObject
基类,例如.Net中内置的类ExpandoObject
,这三者之间的关系是:ExpandoObject,DynamicObject都继承了IDynamicMetaObjectProvider.这种情
况下,只有DynamicMetaObject.GetDynamicMemberNames的返回的成员的属性会被序列化.

首先新建一个类,继承基类 DynamicObject

    public class MyDynamic : DynamicObject
{
//用来存储动态添加的变量和值
private Dictionary<string, object> members = new Dictionary<string, object>(); /// <summary>
/// 获取所有的动态成员名称
/// </summary>
/// <returns>动态成员名称</returns>
public override IEnumerable<string> GetDynamicMemberNames()
{
return members.Keys;
} /// <summary>
/// 设置动态成员名称,也就是在发生赋值语句时出发该方法
/// 例如:dynamic dy = new MyDynamic();
/// dy.Name = "Jack";
/// </summary>
/// <param name="binder">用于动态设置操作</param>
/// <param name="value">预设的值</param>
/// <returns></returns>
public override bool TrySetMember(SetMemberBinder binder, object value)
{
if (!members.ContainsKey(binder.Name))
{
members.Add(binder.Name, value);
}
else
members[binder.Name] = value;
return true;
} /// <summary>
/// 根据名称获取动态成员的值
/// 例如:dynamic dy = new MyDynamic();
/// var name = dy.Name;
/// </summary>
/// <param name="binder">用户动态获取操作</param>
/// <param name="result">将获取的值赋给的对象</param>
/// <returns></returns>
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
if (members.ContainsKey(binder.Name))
{
result = members[binder.Name];
return true;
}
else
return base.TryGetMember(binder, out result);
} /// <summary>
/// 如果成员的类型是委托,则调用它
/// </summary>
/// <param name="binder">用户动态委托操作</param>
/// <param name="args">委托调用的参数</param>
/// <param name="result">委托调用返回的结果</param>
/// <returns></returns>
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
{
if (members.ContainsKey(binder.Name) && members[binder.Name] is Delegate)
{
result = (members[binder.Name] as Delegate).DynamicInvoke(args);
return true;
}
else
{
return base.TryInvokeMember(binder, args, out result);
}
}
}

在主程序中,做如下操作:

            dynamic md = new MyDynamic();//必须是用dynamic来声明变量,不能用MyDynamic,否则它就不是动态类型了。
md.Name = "Jack";
Action<string> output = new Action<string>((value) => { Console.WriteLine(value); });
md.Output = output;
Console.WriteLine(JsonConvert.SerializeObject(md));
md.Output(md.Name);

结果:

是的,委托类型也被序列化了,这并不是我们想要的,有没有方法来将它排除呢?答案就在GetDynamicMemberNames方法,默认我们返回的是所有的Keys,只要我们加一定的限制条件即可.修改之后的代码

        public override IEnumerable<string> GetDynamicMemberNames()
{
foreach (string key in members.Keys)
{
if(!(members[key] is Delegate))
yield return key;
}
}

此时的运行结果:

OK!有什么问题,请及时告诉我啊!一起学习!

Json.Net系列教程 2.Net类型与JSON的映射关系的更多相关文章

  1. Json.Net系列教程 3.Json.Net序列化和反序列化设置

    原文 Json.Net系列教程 3.Json.Net序列化和反序列化设置 上节补充 首先补充一点,Json.Net是支持序列化和反序列化DataTable,DataSet,Entity Framewo ...

  2. Json.Net系列教程 1.Json.Net介绍及实例

    原文 Json.Net系列教程 1.Json.Net介绍及实例 本系列教程假设读者已经对Json有一定的了解,关于Json在这里不多说.本系列教程希望能对读者开发涉及到Json的.Net项目有一定的帮 ...

  3. Json.Net系列教程 4.Linq To JSON

    原文 Json.Net系列教程 4.Linq To JSON 更改历史 2013-05-31 添加一个FAQ   一.Linq to JSON是用来干什么的? Linq to JSON是用来操作JSO ...

  4. .NET 中,编译器直接支持的数据类型称为基元类型(primitive type).基元类型和.NET框架类型(FCL)中的类型有直接的映射关系.

    .NET 中,编译器直接支持的数据类型称为基元类型(primitive type).基元类型和.NET框架类型(FCL)中的类型有直接的映射关系. The primitive types are Bo ...

  5. 使用Newtonsoft.json 解决 Asp.Net MVC DateTime类型数据Json格式化问题

    解决思路 众所周知,MVC中调用的微软的组件JavaScriptSerialer...,格式DateTime类型数据需要在客户端专门解. 还知道,NewtonSoft.json可以“正确”的格式化Da ...

  6. JPA 系列教程14-自定义类型-@Embedded+@Embeddable

    自定义类型 在hibernate中实现自定义类型,需要去实现UserType接口即可或者以Component的形式提供. JPA的@Embedded注解有点类似,通过此注解可以在Entity模型中使用 ...

  7. thinkphp5操作redis系列教程】列表类型之lRange,lGetRange

    <?php namespace app\admin\controller; use think\cache\driver\Redis; use think\Controller; use \th ...

  8. JNI类型与C/C++映射关系

    Java 类型 本地类型 描述 boolean jboolean C/C++8位整型 byte jbyte C/C++带符号的8位整型 char jchar C/C++无符号的16位整型 short ...

  9. 关系类型字段 -- Django从入门到精通系列教程

    该系列教程系个人原创,并完整发布在个人官网刘江的博客和教程 所有转载本文者,需在顶部显著位置注明原作者及www.liujiangblog.com官网地址. Python及Django学习QQ群:453 ...

随机推荐

  1. iOS开发通过代码方式使用AutoLayout (NSLayoutConstraint + Masonry)

    iOS开发通过代码方式使用AutoLayout (NSLayoutConstraint + Masonry) 随着iPhone6/6+设备的上市,如何让手头上的APP适配多种机型多种屏幕尺寸变得尤为迫 ...

  2. JDK源码学习--String篇(四) 终结篇

    StringBuilder和StringBuffer 前面讲到String是不可变的,如果需要可变的字符串将如何使用和操作呢?JAVA提供了连个操作可变字符串的类,StringBuilder和Stri ...

  3. 深度优先搜索——迷宫问题(华为oj)

    题目描述: 定义一个二维数组N*M(其中2<=N<=10;2<=M<=10),如5 × 5数组下所示: int maze[5][5] = { 0, 1, 0, 0, 0, 0, ...

  4. codeforces 535D. Tavas and Malekas KMP

    题目链接 又复习了一遍kmp....之前都忘光了 #include<bits/stdc++.h> using namespace std; #define pb(x) push_back( ...

  5. C#进程管理程序实现

    运行效果图 部分代码如下: #region 打开应用程序按钮事件处理程序 /// <summary> /// 打开应用程序按钮事件处理程序 /// </summary> /// ...

  6. java中三种常见内存溢出错误的处理方法

    更多 10   相信有一定java开发经验的人或多或少都会遇到OutOfMemoryError的问题,这个问题曾困扰了我很长时间,随着解决各类问题经验的积累以及对问题根源的探索,终于有了一个比较深入的 ...

  7. 常用CSS HACK

    常用CSS HACK IE6 3像素bug和双边距bug一样的经典 现象: IE6下浮动元素和不浮动元素之间会有3px间隙(3px bug,div.float-left + div.float-non ...

  8. Win7下使用protel99se、protel99

    很多网友需要用的protel99se,由于该软件开发的时间比较就早,在现在笔记本普及,尤其是win7普及的情况下,用该软件着实让许多人头痛,有人选择安装XP系统,但这就牺牲了win7良好的操作体验.也 ...

  9. 数学之路(3)-机器学习(3)-机器学习算法-SVM[7]

    SVM是新近出现的强大的数据挖掘工具,它在文本分类.手写文字识别.图像分类.生物序列分析等实际应用中表现出非常好的性能.SVM属于监督学习算法,样本以属性向量的形式提供,所以输入空间是Rn的子集. 图 ...

  10. 【Perl学习笔记】2. perl中的bless理解

    bless有两个参数:对象的引用.类的名称. 类的名称是一个字符串,代表了类的类型信息,这是理解bless的关键. 所谓bless就是把 类型信息 赋予 实例变量. 程序包括5个文件:person.p ...