Newtonsoft.Json序列化库

Unity自己的Json序列化是不支持字典格式的,而且功能比较单一,这里介绍一个.Net中开源的Json序列化和反序列化库和基本用法以及常用的数据处理方法(github地址:https://github.com/JamesNK/Newtonsoft.Json/releases )(百度网盘:链接:https://pan.baidu.com/s/1S4cQW3NoU-g5AMPZ8VKzvQ 提取码:b19e ),

数据处理接口

这里的接口包含数据序列化反序列化两个方法,因为可能会碰到Json,Xml,二进制或者其他的结构。

public interface IObjectSerializer
{
    string Serializer<T>(T obj);

    T DeSerializer<T>(string content);

}

 

设置Json键统一

数据处理时我们可以设置 JsonSerializerSettings ,在数据处理时字段名转换为驼峰命名法,(比如我们客户端用的是大驼峰法,Java服务器习惯用的小驼峰法)也就是说当我们客户端的代码为 pubilc string Name = "Alice";时,经过序列化后的字符串后会变为 "name"="Alice",而不是"Name" = "Alice";

ContractResolver = new CamelCasePropertyNamesContractResolver()对 JSON 数据使用混合大小写。驼峰式,但是是javascript 首字母小写形式.

当然我们也可以继承DefaultContractResolver,重写ResolveContract方法去处理其他格式的字段名比如说字段名全小写,或者去除字段下划线。

另外这里序列化的类可以使用单利模式处理,这里因为要另外上传单利模板类,为了方便大家直接拿到可以使用,我就不再麻烦写了。

using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;

public class JsonObjectSerializer : IObjectSerializer
{
    private readonly JsonSerializerSettings settings = new JsonSerializerSettings() { ContractResolver = new CamelCasePropertyNamesContractResolver() };

    public T DeSerializer<T>(string content)
    {
        if (typeof(T)==typeof(string))
        {
            return (T)(object)content;
        }
        else
        {
            return JsonConvert.DeserializeObject<T>(content);
        }
    }

    public string Serializer<T>(T obj)
    {
        return JsonConvert.SerializeObject(obj, this.settings);
    }
}

空值类型处理

当我们反序列化中碰到不可为空的数据类型,而传过来的json中值是null时,会出现反序列化失败比如说Java中的包装类型 int number =null,如果我们C#中直接用 int number; 去接这个数据时就会出错,当然我们也可以提前设置为可空类型的int,int? number = null;或者 Nullable<int> a = null; 

也可以用下面这种实现JsonConVerter方法来处理

[JsonConverter(typeof(ValueTypeNullToDefaultConverter))]
           public long Id { get; set; }

当接收到的是 { "Id" = null } 会序列化为 long类型的默认值 0  Id = 0;

using Newtonsoft.Json;
using System;
using UnityEngine;

public class ValueTypeNullToDefaultConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType.IsValueType;
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.Value == null)
        {
            return Activator.CreateInstance(objectType);
        }

        return this.ChangeType(reader.Value, objectType);
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        writer.WriteRawValue(value == null ? null : value.ToString());
    }

    public object ChangeType(object value, Type objectType)
    {
        if (value == null)
        {
            return null;
        }

        try
        {
            return Convert.ChangeType(value, objectType);
        }
        catch (Exception ex)
        {
            Debug.LogError(string.Format("[ChangeType]:Failed to change object value '{0}' to object type '{1}',Exception:{2}", value, objectType.Name,ex));
            return null;
        }
    }
}

日期格式处理

DateTime类型系统自带的会格式化成iso日期标准"UpdateTime" = "2019-03-31T00:00:00",但是实际使用过程中我们可能要的是yyyy-MM-dd或者yyyy-MM-dd HH:mm:ss,或者是传给后台的减去自己所在时区的毫秒数,或者后台传回来的毫秒数要加上自己当前时区的毫秒数,这里给出的后一种的解决办法。

using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System;

public class UnixDateTimeConverter : DateTimeConverterBase
{
    public static readonly DateTime BaseTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
    public static readonly DateTime StartTime = TimeZone.CurrentTimeZone.ToLocalTime(BaseTime);//当地时区

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.Value ==null)
        {
            return null;
        }

        return BaseTime.AddMilliseconds((long)reader.Value).ToLocalTime();
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        if (value!=null)
        {
            var dateTime = (DateTime)value;
            writer.WriteRawValue(((long)(dateTime - StartTime).TotalMilliseconds).ToString());
        }
    }
}

枚举值自定义格式化

一般情况下枚举值的序列化会自动格式化成枚举对应的整型数值,比如说:

pubilce enum Gender

{

Male = 0,

Female = 1,

Unknown

}

public Gender Gender = Male;

序列化后为:{"Gender:0"}

只要在 Gender属性上机上JsonConverter(typeof(StringEnumConverter))表示将枚举值转换成对应的字符串,而StringEnumConverter是Newtonsoft.Json内置的转换类型。最终输出结果 {"Gender" = "Male"}

忽略某些属性

当我们遇到接口优化,实体中有些属性不需要序列化返回,可以用该特性,比如说我们在一个实体类中有10个字段,但其中有一个属性序列化后会占用大量的字节,并且这个属性服务器是不需要的,仅供我们客户端逻辑使用。如果这些数据都上传到服务器,会造成带宽的占用,也就是说40K的数据中,会有20K的无效数据,我们要做的就是优化掉这些无效的数据。

OptOut默认值,类中所有公有成员会被序列化,如果不想被序列化,可以用特性JsonIgnore
OptIn默认情况下,所有的成员不会被序列化,类中的成员只有标有特性JsonProperty的才会被序列化,当类的成员很多,但客户端仅仅需要一部分数据时,很有用

 

 

 

[JsonObject(MemberSerialization.OptIn)]

public class UserInfo

{

[JsonProperty]

pubilc string Name { get;set; }

pubilc int Age { get;set; }

}

序列化输出 { "Name" = "Alice" } 只输出姓名字段

 

[JsonObject(MemberSerialization.OptOut)]

public class Person

{

public int Age { get; set; }

[JsonIgnore]

public string Name { get; set; }

 }

序列化输出为{ "Age" = "18" },忽略姓名字段

 

其他处理

using Newtonsoft.Json;
using System;
using System.Collections.Generic;

public class UserInfo
{
    [JsonConverter(typeof(ValueTypeNullToDefaultConverter))]
    public long Id { get; set; }

    [JsonProperty("name")]//将json中的name反序列化时转为UserName
    public string UserName { get; set; }

    [JsonConverter(typeof(UnixDateTimeConverter))]
    public DateTime Birthday { get; set; }

    [JsonProperty(ItemConverterType =typeof(UnixDateTimeConverter))]
    public List<DateTime> LoginTime { get; set; }
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值