Newtonsoft.Json 源码地址:https://github.com/JamesNK/Newtonsoft.Json
作者James Newton-King,现在在微软工作,所以你看.NetCore有些对象映射以及System.Text.Json的方法和用法都是一毛一样的。

从组织一栏,也能看出来,他服务的团队,跟我们用的技术息息相关。
我们先看下我们之前的封装,都干了啥
public static class SerializerHelper
{
/// <summary>
/// JSON序列化
/// </summary>
/// <param name="obj">对象</param>
/// <returns>JSON字符串</returns>
public static string SerializeObject(this object obj)
{
try
{
var jsonSerializerSettings = new JsonSerializerSettings { DateFormatString = "yyyy-MM-dd HH:mm:ss" };
return JsonConvert.SerializeObject(obj, jsonSerializerSettings);
}
catch
{
return string.Empty;
}
}
/// <summary>
/// 反序列化
/// </summary>
/// <typeparam name="T">对象</typeparam>
/// <param name="json">JSON字符串</param>
/// <returns>对象</returns>
public static T DeserializeObject<T>(this string json)
{
try
{
return JsonConvert.DeserializeObject<T>(json);
}
catch
{
return default(T);
}
}
/// <summary>
/// 反序列化
/// </summary>
/// <param name="json">JSON字符串</param>
/// <returns>对象</returns>
public static dynamic DeserializeObject(this string json)
{
try
{
return JsonConvert.DeserializeObject(json);
}
catch
{
return null;
}
}
/// <summary>
/// XML序列化方式深复制
/// </summary>
/// <typeparam name="T">类型</typeparam>
/// <param name="obj">对象</param>
/// <returns>复制对象</returns>
public static T DeepCopy<T>(this T obj)
{
object retval;
using (MemoryStream ms = new MemoryStream())
{
XmlSerializer xml = new XmlSerializer(typeof(T));
xml.Serialize(ms, obj);
ms.Seek(0, SeekOrigin.Begin);
retval = xml.Deserialize(ms);
ms.Close();
}
return (T)retval;
}
/// <summary>
/// 将一个实体对象转换为另一个实体对象
/// </summary>
/// <typeparam name="T1">第一个实体对象</typeparam>
/// <typeparam name="T2">第二个实体对象</typeparam>
/// <param name="source">转换的实体对象</param>
/// <returns></returns>
public static T2 CopyToModel<T1, T2>(T1 source)
{
T2 model = default(T2);
if (source == null)
{
return model;
}
PropertyInfo[] pi = typeof(T2).GetProperties();
PropertyInfo[] pi1 = typeof(T1).GetProperties();
model = Activator.CreateInstance<T2>();
for (int i = 0; i < pi.Length; i++)
{
for (int j = 0; j < pi1.Length; j++)
{
if (pi[i].Name == pi1[j].Name)
{
pi[i].SetValue(model, pi1[j].GetValue(source, null), null);
}
}
}
return model;
}
/// <summary>
/// 将一个实体对象转换为另一个实体对象
/// </summary>
/// <typeparam name="T1">第一个实体对象</typeparam>
/// <typeparam name="T2">第二个实体对象</typeparam>
/// <param name="source">转换的实体对象</param>
/// <returns></returns>
public static List<T2> CopyToModel<T1, T2>(List<T1> source)
{
List<T2> modelList = new List<T2>();
if (!source.Any())
{
return modelList;
}
PropertyInfo[] pi = typeof(T2).GetProperties();
PropertyInfo[] pi1 = typeof(T1).GetProperties();
foreach (T1 obj in source)
{
T2 model = Activator.CreateInstance<T2>();
for (int i = 0; i < pi.Length; i++)
{
for (int j = 0; j < pi1.Length; j++)
{
if (pi[i].Name == pi1[j].Name)
{
pi[i].SetValue(model, pi1[j].GetValue(obj, null), null);
}
}
}
modelList.Add(model);
}
return modelList;
}
}这个类其实满足了我们平时大部分需求,但是在.NetCore中,很多东西被封装到了底层,由对象映射直接处理,不需要我们写这些方法了,由System.Test.Json提供支持。
这个类针对的都是string格式和对象中的类型能对应的情况。
接下来说几个不满足的:
1、json字符串中是时间戳,但是实体类中类型是DateTime
2、json字符串中是“41.0”,但是实体类中是Int
3、再比如Mongodb中的那一堆类型,没有能直接操作的,都需要转换后才能使用,比如ObjectId、Decimal128
细看这几个类型,其实还是有那么点联系的,“41.0”首先是字符串,其次更加接近浮点数,最后才是整数;ObjectId其实是UUID的格式,对应的就是一串字符串;Decimal128对应的就是Decimal。
我以第一个时间戳字符串反序列化DateTime为例。
1、先定义自定义转换器
public class DateTimeConverter : JsonConverter
{
/// <summary>
///转json字符串
/// </summary>
/// <param name="writer">The <see cref="T:Newtonsoft.Json.JsonWriter" /> to write to.</param>
/// <param name="value">The value.</param>
/// <param name="serializer">The calling serializer.</param>
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
serializer.Serialize(writer, value);
}
/// <summary>
///字符串转对象
/// </summary>
/// <param name="reader">The <see cref="T:Newtonsoft.Json.JsonReader" /> to read from.</param>
/// <param name="objectType">Type of the object.</param>
/// <param name="existingValue">The existing value of object being read.</param>
/// <param name="serializer">The calling serializer.</param>
/// <returns>
/// The object value.
/// </returns>
public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
JsonSerializer serializer)
{
try
{
JToken token = JToken.Load(reader);
string time = token.ToObject<string>();
DateTime dt;
if (time.Length <= 13)
{
dt = ConvertStringToDateTime(time);
}
else
{
dt = Convert.ToDateTime(time);
}
return dt;
}
catch
{
return DateTime.MinValue;
}
}
/// <summary>
/// Determines whether this instance can convert the specified object type.
/// </summary>
/// <param name="objectType">Type of the object.</param>
/// <returns>
/// <c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
/// </returns>
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(DateTime));
}
/// <summary>
/// 将c# DateTime时间格式转换为Unix时间戳格式
/// </summary>
/// <param name="time">时间</param>
/// <returns>long</returns>
public static long ConvertDateTimeToInt(System.DateTime time)
{
System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1, 0, 0, 0, 0));
long t = (time.Ticks - startTime.Ticks) / 10000; //除10000调整为13位
return t;
}
/// <summary>
/// 时间戳转C#时间
/// </summary>
/// <param name="timeStamp">The time stamp.</param>
/// <returns></returns>
public static DateTime ConvertStringToDateTime(string timeStamp)
{
DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
long lTime = long.Parse(timeStamp + "0000");
TimeSpan toNow = new TimeSpan(lTime);
return dtStart.Add(toNow);
}
}这个转换器中,以下方法是必须要有的:
1、WriteJson:序列化时使用(对象转JSON字符串)
2、ReadJson:反序列化时使用(JSON字符串转对象)
3、CanConvert:确定转换器实例是否可以转换指定的对象类型
所以我们要实现时间戳字符串转DataTime,只需要着重于ReadJson方法的重写。
实体类中加个特性,如下:
public class UserInfo
{
/// <summary>
/// Gets or sets the name of the user.
/// </summary>
public string UserName { get; set; }
/// <summary>
/// Gets or sets the create time.
/// </summary>
[JsonConverter(typeof(DateTimeConverter))]
public DateTime CreateTime { get; set; }
}可以看到我将字符串取到之后,判断了长度是否为时间戳,然后转换之后返回的。
使用如下:
string str = "{\"UserName\":\"123\",\"CreateTime\":\"1592542123500\"}";
UserInfo item = str.DeserializeObject<UserInfo>();
str = item.SerializeObject();
UserInfo item2 = str.DeserializeObject<UserInfo>();
Console.WriteLine(item2.SerializeObject());
如果想DateTime能还原回时间戳,修改一下WriteJson方法即可。
如果遇到其他情况,做法差不多,都是取到源字符串,用自己的方法进行处理即可。
川公网安备 51010702003150号
留下您的脚步
最近评论