.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(1);
 ma.Add(2);
 ma.Add(3);
 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!有什么问题,请及时告诉我啊!一起学习!

.Net类型与JSON的映射关系

时间: 2024-11-08 02:45:43

.Net类型与JSON的映射关系的相关文章

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

.NET 中,编译器直接支持的数据类型称为基元类型(primitive type).基元类型和.NET框架类型(FCL)中的类型有直接的映射关系. The primitive types are Boolean, Byte, SByte, Int16, UInt16, Int32, UInt32, Int64, UInt64, IntPtr, UIntPtr, Char, Double, and Single. https://msdn.microsoft.com/zh-cn/library/s

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

Java 类型 本地类型 描述 boolean jboolean C/C++8位整型 byte jbyte C/C++带符号的8位整型 char jchar C/C++无符号的16位整型 short jshort C/C++带符号的16位整型 int jint C/C++带符号的32位整型 long jlong C/C++带符号的64位整型e float jfloat C/C++32位浮点型 double jdouble C/C++64位浮点型 Object jobject 任何Java对象,或

Hibernate @Temporal 注解处理Java与Mysql时间日期类型的映射关系

2017-4-2 在 Java 中使用 java.util.Date 和 java.util.Calendar 表示时间.日期类型.在 Mysql 中使用 YEAR.DATE.TIME.TIMESTAMP.DATETIME 五种数据类型表示时间日期,由此引出了 Java 日期类型跟数据库的日期类型怎么映射的问题.本文总结了使用 Hibernate @Temporal 注解的解决方案. 使用 @Temporal 注解修饰 Java 实体类的数据类型 指定 @Temporal value 属性,其中

Hibernate基本配置:类与表之间的映射关系

只介绍用Annotation的方式进行映射关系的配置. 1. 如果表名与对象名不一致,则要对表名进行配置. 使用@Table 2. 如果字段名与属性名不一致. 使用@Column 3. 不需要persistentence的字段 使用@Persistentence 4.映射日期与时间类型,指定时间精度 使用@Temporal 默认会直接记录日期与时分秒,可以进行定制. @Temporal(TemporalType.?),?可以取3个值,DTAE(只记录日期),TIME(记录时分秒),TIMESTA

MyBatis --- 映射关系【一对一、一对多、多对多】,懒加载机制

映射(多.一)对一的关联关系 1)若只想得到关联对象的id属性,不用关联数据表 2)若希望得到关联对象的其他属性,要关联其数据表 举例: 员工与部门的映射关系为:多对一 1.创建表 员工表 确定其外键是部门表的 id DROP TABLE IF EXISTS emp; CREATE TABLE emp( id INT(11) NOT NULL PRIMARY KEY AUTO_INCREMENT, emp_name VARCHAR(255) DEFAULT NULL, gender CHAR(1

SSH深度历险(一)深入浅出Hibernate架构(一)-------映射解析——七种映射关系

        ORM.全称是(Object Relational Mapping),即对象关系映射.ORM的实现思想就是将关系数据库中表的数据映射成对象.以对象的形式展现.这样开发者就能够把对数据库的操作转化为对这些对象的操作.Hibernate正是实现了这样的思想,达到了方便开发者以面向对象的思想来实现对数据库的操作.    Hibernate在实现ORM功能的时候主要用到的文件有:映射类(*.java).映射文件(*.hbm.xml)和数据库配置文件(*.properties/*.cfg.

NHibernate 映射关系

基本映射关系如下: NHibernate类型 .NET类型 Database类型 备注 AnsiChar System.Char DbType.AnsiStringFixedLength - 1 char Boolean System.Boolean DbType.Boolean 在没有指定类型(type) 属性时的默认值. Byte System.Byte DbType.Byte 在没有指定类型(type) 属性时的默认值. Char System.Char DbType.StringFixe

hibernate注解方式来处理映射关系

在hibernate中,通常配置对象关系映射关系有两种,一种是基于xml的方式,另一种是基于annotation的注解方式,熟话说,萝卜青菜,可有所爱,每个人都有自己喜欢的配置方式,我在试了这两种方式以后,发现使用annotation的方式可以更简介,所以这里就简单记录下通过annotation来配置各种映射关系,在hibernate4以后已经将annotation的jar包集成进来了,如果使用hibernate3的版本就需要引入annotation的jar包. 一.单对象操作 @Entity

注册URL模式与HttpHandler的映射关系

注册URL模式与HttpHandler的映射关系 ASP.NET Core的路由是通过一个类型为RouterMiddleware的中间件来实现的.如果我们将最终处理HTTP请求的组件称为HttpHandler,那么RouterMiddleware中间件的意义在于实现请求路径与对应HttpHandler之间的映射关系.对于传递给RouterMiddleware中间件的每一个请求,它会通过分析请求URL的模式并选择并提取对应的HttpHandler来处理该请求.除此之外,请求的URL还会携带相应参数