zoukankan      html  css  js  c++  java
  • Json.Net系列教程 2.Net类型与JSON的映射关系

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

    https://www.cnblogs.com/usharei/archive/2012/04/19/2456698.html

    首先谢谢大家的支持和关注.本章主要介绍.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!有什么问题,请及时告诉我啊!一起学习!

  • 相关阅读:
    微软推出的免费新书《Introducing Microsoft SQL Server 2012》
    关于Installshield中Ie8\Ie9\SQL Server 2008 R2 Native Client等Prq文件在线下载地址
    PowerDesigner批量生成日期型、中文字符型、数字型测试数据
    在服务器上使用第三方独立组件对Word/Excel进行编程
    文明源自谎言
    中文写程序,何陋之有?
    在线网摘收藏?让Google来吧!
    下载文件时根据MIME类型自动判断保存文件的扩展名
    谨慎注意WebBrowser控件的DocumentCompleted事件
    你的命运谁攥着?
  • 原文地址:https://www.cnblogs.com/bwdblogs/p/11087660.html
Copyright © 2011-2022 走看看