欢迎来到陆季疵的博客

人生莫作远行客,远行莫戍黄沙碛。黄沙碛下八月时, 霜风裂肤百草衰。尘沙晴天迷道路,河水悠悠向东去。 胡笳听彻双泪流,羁魂惨惨生边愁。原头猎火夜相向, 马蹄蹴蹋层冰上。不似京华侠少年,清歌妙舞落花前。

JSON入门篇

一、简介

JSON: JavaScript Object Notation(JavaScript 对象表示法)

JSON 是存储和交换文本信息的语法,类似 XML。

JSON 比 XML 更小、更快,更易解析。

第一个JSON示例:这个 sites 对象是包含 3 个站点记录(对象)的数组。

{
    "sites": [
    { "name":"菜鸟教程" , "url":"www.runoob.com" }, 
    { "name":"google" , "url":"www.google.com" }, 
    { "name":"微博" , "url":"www.weibo.com" }
    ]
}

什么是 JSON ?

  • JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation)
  • JSON 是轻量级的文本数据交换格式
  • JSON 独立于语言:JSON 使用 Javascript语法来描述数据对象,但是 JSON 仍然独立于语言和平台。JSON 解析器和 JSON 库支持许多不同的编程语言。 目前非常多的动态(PHP,JSP,.NET)编程语言都支持JSON。
  • JSON 具有自我描述性,更易理解

JSON - 转换为 JavaScript 对象

JSON 文本格式在语法上与创建 JavaScript 对象的代码相同。

由于这种相似性,无需解析器,JavaScript 程序能够使用内建的 eval() 函数,用 JSON 数据来生成原生的 JavaScript 对象。

与 XML 相同之处

  • JSON 是纯文本
  • JSON 具有"自我描述性"(人类可读)
  • JSON 具有层级结构(值中存在值)
  • JSON 可通过 JavaScript 进行解析
  • JSON 数据可使用 AJAX 进行传输

与 XML 不同之处

  • 没有结束标签
  • 更短
  • 读写的速度更快
  • 能够使用内建的 JavaScript eval() 方法进行解析
  • 使用数组
  • 不使用保留字

为什么使用 JSON?

对于 AJAX 应用程序来说,JSON 比 XML 更快更易使用:

使用 XML

  • 读取 XML 文档
  • 使用 XML DOM 来循环遍历文档
  • 读取值并存储在变量中

使用 JSON

  • 读取 JSON 字符串
  • 用 eval() 处理 JSON 字符串

二、JSON 语法

JSON 语法规则

JSON 语法是 JavaScript 对象表示语法的子集。

  • 数据在名称/值对中
  • 数据由逗号分隔
  • 大括号 {} 保存对象
  • 中括号 [] 保存数组,数组可以包含多个对象

JSON 名称/值对

JSON 数据的书写格式是:

key : value

JSON 值

JSON 值可以是:

  • 数字(整数或浮点数)
  • 字符串(在双引号中)
  • 逻辑值(true 或 false)
  • 数组(在中括号中)
  • 对象(在大括号中)
  • null

JSON 数字

JSON 数字可以是整型或者浮点型:

{ "age":30 }

JSON 对象

JSON 对象在大括号 {} 中书写:

{key1 : value1, key2 : value2, ... keyN : valueN }

JSON 数组

JSON 数组在中括号 [] 中书写:

数组可包含多个对象:

[
    { key1 : value1-1 , key2:value1-2 }, 
    { key1 : value2-1 , key2:value2-2 }, 
    { key1 : value3-1 , key2:value3-2 }, 
    ...
    { keyN : valueN-1 , keyN:valueN-2 }, 
]

JSON 布尔值

JSON 布尔值可以是 true 或者 false:

{ "flag":true }

JSON null

JSON 可以设置 null 值:

{ "runoob":null }

三、JSON 对象

JSON 对象使用在大括号({})中书写。

对象可以包含多个 key/value(键/值)对。

key 必须是字符串,value 可以是合法的 JSON 数据类型(字符串, 数字, 对象, 数组, 布尔值或 null)。

key 和 value 中使用冒号(:)分割。

每个 key/value 对使用逗号(,)分割。

访问对象值

你可以使用点号(.)来访问对象的值:

var myObj, x;
myObj = { "name":"runoob", "alexa":10000, "site":null };
x = myObj.name;

你也可以使用中括号([])来访问对象的值:

var myObj, x;
myObj = { "name":"runoob", "alexa":10000, "site":null };
x = myObj["name"];

循环对象

你可以使用 for-in 来循环对象的属性:

var myObj = { "name":"runoob", "alexa":10000, "site":null };
for (x in myObj) {
    document.getElementById("demo").innerHTML += x + "<br>";
}

在 for-in 循环对象的属性时,使用中括号([])来访问属性的值:

var myObj = { "name":"runoob", "alexa":10000, "site":null };
for (x in myObj) {
    document.getElementById("demo").innerHTML += myObj[x] + "<br>";
}

嵌套 JSON 对象

JSON 对象中可以包含另外一个 JSON 对象:

myObj = {
    "name":"runoob",
    "alexa":10000,
    "sites": {
        "site1":"www.runoob.com",
        "site2":"m.runoob.com",
        "site3":"c.runoob.com"
    }
}

你可以使用点号(.)或者中括号([])来访问嵌套的 JSON 对象。

x = myObj.sites.site1;
// 或者
x = myObj.sites["site1"];

删除对象属性

我们可以使用 delete 关键字来删除 JSON 对象的属性:

delete myObj.sites.site1;

Json 格式化工具   JSON 在线解析 | 菜鸟工具 (runoob.com)


 

.NET解析JSON

使用 Newtonsoft.Json 包解析

1、基本用法

Json.Net是支持序列化和反序列化DataTable,DataSet,Entity FrameworkEntity的。下面分别举例说明序列化和反序列化。

            //序列化DataTable
            DataTable dt = new DataTable();
            dt.Columns.Add("Age", Type.GetType("System.Int32"));
            dt.Columns.Add("Name", Type.GetType("System.String"));
            dt.Columns.Add("Sex", Type.GetType("System.String"));
            dt.Columns.Add("IsMarry", Type.GetType("System.Boolean"));
            for (int i = 0; i < 4; i++)
            {
                DataRow dr = dt.NewRow();
                dr["Age"] = i + 1;
                dr["Name"] = "Name" + i;
                dr["Sex"] = i % 2 == 0 ? "" : "";
                dr["IsMarry"] = i % 2 > 0 ? true : false;
                dt.Rows.Add(dr);
            }
            Console.WriteLine(JsonConvert.SerializeObject(dt));

            //字符串进行反序列化
            string json = JsonConvert.SerializeObject(dt);
            dt = JsonConvert.DeserializeObject<DataTable>(json);
            foreach (DataRow dr in dt.Rows)
            {
                Console.WriteLine("{0}\t{1}\t{2}\t{3}\t", dr[0], dr[1], dr[2], dr[3]);
            }

 

 2、高级用法

  1. 忽略某些属性
  2. 默认值的处理
  3. 空值的处理
  4. 支持非公共成员
  5. 日期处理
  6. 自定义序列化的字段名称
  7. 动态决定属性是否序列化
  8. 枚举值的自定义格式化问题
  9. 自定义类型转换
  10. 全局序列化设置

 2.1属性特性标记 通过JsonProperty属性设置的方法,可以实现某一属性特别处理的需求,如默认值处理,空值处理,自定义属性名处理,格式化处理。上面空值处理实现

序列化时默认都是处理公共成员,如果需要处理非公共成员,就要在该成员上加特性[JsonProperty]

        [JsonProperty(PropertyName = "图层颜色")]
        public int? ColorIndex { get; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public Room room { get; set; }
[DefaultValue(10)]
public int Age { get; set; }
    [JsonIgnore]
    public bool IsMarry { get; set; }

2.2 对象特性标记  [JsonObject(MemberSerialization.OptOut)] 可以设置输出形式

    [JsonObject(MemberSerialization.OptOut)]
    class LayerValue:ValueBase
    {
        [JsonProperty(PropertyName = "块名称")]
        public string? BlockName { get; }
        [JsonProperty(PropertyName = "图层名称")]
        public string? Layer { get; }
        [JsonProperty(PropertyName = "图层颜色")]
        public int? ColorIndex { get; }

        public LayerValue():base()
        {

        }
    }

2.3属性类型转换

枚举类型转换

        [JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
        public FileMode Mode { get; set; } = FileMode.Create;

日期处理

  对于Dateime类型日期的格式化就比较麻烦了,系统自带的会格式化成iso日期标准"Birthday":"1991-01-02T00:00:00,但是实际使用过程中大多数使用的可能是yyyy-MM-dd或者yyyy-MM-dd HH:mm:ss两种格式的日期,

解决办法是可以将DateTime类型改成string类型自己格式化好,然后再序列化。如果不想修改代码,可以采用下面方案实现。Json.Net提供了IsoDateTimeConverter日期转换这个类,可以通过JsnConverter实现相应的日期转换

        [JsonConverter(typeof(Newtonsoft.Json.Converters.IsoDateTimeConverter))]
        public DateTime Birthday { get; set; }

2.4自定义类型转换

自定义一个日期类型转换

        [JsonConverter(typeof(ChinaDateTimeConverter))]
        public DateTime Birthday { get; set; }
    /// <summary>
    /// 自己实现了一个yyyy-MM-dd格式化转换类
    /// </summary>
    public class ChinaDateTimeConverter : Newtonsoft.Json.Converters.DateTimeConverterBase
    {
        private static Newtonsoft.Json.Converters.IsoDateTimeConverter dtConverter = new Newtonsoft.Json.Converters.IsoDateTimeConverter { DateTimeFormat = "yyyy-MM-dd" };
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            return dtConverter.ReadJson(reader, objectType, existingValue, serializer);
        }
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            dtConverter.WriteJson(writer, value, serializer);
        }
    }

自定义了BoolConvert类型,继承自JsonConverter。构造函数参数BooleanString可以让我们自定义将true false转换成相应字符串。下面看实体里面怎么使用这个自定义转换类型

默认情况下对于实体里面的Boolean系统是格式化成true或者false,对于true转成"是" false转成"否"这种需求改怎么实现了?我们可以自定义类型转换实现该需求,下面看实例

        [JsonConverter(typeof(BoolConvert))]
        public bool IsMarry { get; set; }
    public class BoolConvert : JsonConverter
    {
        private string[] arrBString { get; set; }

        public BoolConvert()
        {
            arrBString = "是,否".Split(',');
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="BooleanString">将`bool`值转换成的字符串值</param>
        public BoolConvert(string BooleanString)
        {
            if (string.IsNullOrEmpty(BooleanString))
            {
                throw new ArgumentNullException();
            }
            arrBString = BooleanString.Split(',');
            if (arrBString.Length != 2)
            {
                throw new ArgumentException("BooleanString格式不符合规定");
            }
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            bool isNullable = IsNullableType(objectType);
            Type t = isNullable ? Nullable.GetUnderlyingType(objectType) : objectType;
            if (reader.TokenType == JsonToken.Null)
            {
                if (!IsNullableType(objectType))
                {
                    throw new Exception(string.Format("不能转换null value to {0}.", objectType));
                }
                return null;
            }
            try
            {
                if (reader.TokenType == JsonToken.String)
                {
                    string boolText = reader.Value.ToString();
                    if (boolText.Equals(arrBString[0], StringComparison.OrdinalIgnoreCase))
                    {
                        return true;
                    }
                    else if (boolText.Equals(arrBString[1], StringComparison.OrdinalIgnoreCase))
                    {
                        return false;
                    }
                }
                if (reader.TokenType == JsonToken.Integer)
                {
                    return Convert.ToInt32(reader.Value) == 1;
                }
            }
            catch
            {
                throw new Exception(string.Format("Error converting value {0} to type '{1}'", reader.Value, objectType));
            }
            throw new Exception(string.Format("Unexpected token {0} when parsing enum", reader.TokenType));
        }

        /// <summary>
        /// 判断是否为`Bool`类型
        /// </summary>
        /// <param name="objectType">类型</param>
        /// <returns>为`bool`类型则可以进行转换</returns>
        public override bool CanConvert(Type objectType)
        {
            return true;
        }

        public bool IsNullableType(Type t)
        {
            if (t == null)
            {
                throw new ArgumentNullException("t");
            }
            return (t.BaseType.FullName == "System.ValueType" && t.GetGenericTypeDefinition() == typeof(Nullable<>));
        }

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            if (value == null)
            {
                writer.WriteNull(); return;
            }
            bool bValue = (bool)value; if (bValue)
            {
                writer.WriteValue(arrBString[0]);
            }
            else
            {
                writer.WriteValue(arrBString[1]);
            }
        }
    }

2.5自定义属性解析类

            JsonSerializerSettings jsetting = new JsonSerializerSettings();
            jsetting.ContractResolver = new LimitPropsContractResolver(new string[] { nameof(LayerValue.Name), nameof(LayerValue.ColorIndex) });
            Console.WriteLine(JsonConvert.SerializeObject(layerValue, Formatting.Indented, jsetting));
    public class LimitPropsContractResolver : Newtonsoft.Json.Serialization.DefaultContractResolver
    {
        string[] props = null;
        bool retain;
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="props">传入的属性数组</param>
        /// <param name="retain">true:表示`props`是需要保留的字段`false`:表示`props`是要排除的字段</param>
        public LimitPropsContractResolver(string[] props, bool retain = true)
        {
            //指定要序列化属性的清单
            this.props = props;
            this.retain = retain;
        }

        protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
        {
            IList<JsonProperty> list = base.CreateProperties(type, memberSerialization); //只保留清单有列出的属性
            return list.Where(p =>
            {
                if (retain)
                {
                    return props.Contains(p.PropertyName);
                }
                else
                {
                    return !props.Contains(p.PropertyName);
                }
            }).ToList();
        }
    }

全局设置

            Newtonsoft.Json.JsonSerializerSettings setting = new Newtonsoft.Json.JsonSerializerSettings();
            JsonConvert.DefaultSettings = new Func<JsonSerializerSettings>(() => {
                //日期类型默认格式化处理
                setting.DateFormatHandling = Newtonsoft.Json.DateFormatHandling.MicrosoftDateFormat;
                setting.DateFormatString = "yyyy-MM-dd HH:mm:ss";
                //空值处理
                setting.NullValueHandling = NullValueHandling.Ignore;
                //高级用法九中的`Bool`类型转换设置
                //setting.Converters.Add(new BoolConvert("是,否"));
                return setting;
            });

 序列化为文件

            WeatherForecast weatherForecast = new WeatherForecast
            {
                Date = DateTime.Now,
                TemperatureCelsius = 20,
                Summary = "it is a good day!"
            };
            string jsonString = JsonConvert.SerializeObject(weatherForecast, Formatting.Indented);
            File.WriteAllText("weather.json", jsonString);

从资源文件读取json

            Assembly assm = Assembly.GetExecutingAssembly();
            using (var reader = new StreamReader( assm.GetManifestResourceStream("ConsoleApp.Jsons.weatherPocos.json")))
            {
                using (JsonTextReader jsonText = new JsonTextReader(reader))
                {
                    JObject jsonObject = (JObject)Newtonsoft.Json.Linq.JToken.ReadFrom(jsonText);
                    Console.WriteLine(jsonObject);
                    var withPOCOs = JsonConvert.DeserializeObject<WeatherForecastWithPOCOs>(jsonObject.ToString());
                }
            }

保存内容到本地文件

            string jsonString;
            using (var reader = new StreamReader(assm.GetManifestResourceStream("ConsoleApp.Jsons.weatherPocos.json"), System.Text.Encoding.UTF8))
            {
                jsonString = reader.ReadToEnd();
            }
            JObject jobject = JObject.Parse(jsonString);//解析成json
            string convertString = Convert.ToString(jobject);//将json装换为string
            File.WriteAllText("ConsoleApp.Jsons.weatherPocos.json", convertString, System.Text.Encoding.UTF8);//将内容写进jon文件中

 

 

参考链接  C# Newtonsoft.Json 高级用法 - 五维思考 - 博客园 (cnblogs.com)  //  Newtonsoft—Json.NET常用方法简述 (lagou.com)

https://blog.csdn.net/q__y__L/article/details/116922418

 

从 Newtonsoft.Json 迁移到 System.Text.Json - .NET | Microsoft Docs

 

posted @ 2021-11-26 12:36  陆季疵  阅读(273)  评论(0编辑  收藏  举报
//《!--看板娘--> //https://www.cnblogs.com/ZTianming/p/14618913.html