1 JSON 的用法
C#中常用 json 保存与分享数据。其中的过程主要是:
(1)程序内的 Class 或 List 或 Hashtable ... -> 序列化为 json 文件或 stream;
(2)加密、传送、接收、解密、(保存 或 不保存)等;
(3)json 反序列化为 Class 或 List 或 Hashtable 等等,用于程序的计算;
2 JSON 序列化 与 反序列化
大家一般都使用 Newtonsoft.Json 进行 json 的序列化与反序列化。
使用 nuget 即可方便使用。
序列化就是将类(内存中定义的一种数据类型):
class mate
{
public int Id { get; set; } = -1;
public string Name { get; set; } = "";
public mate(int id, string name) { Id = id; Name = name; }
}
比如:其中的实例(内存中的数据):
mate one = new mate(110101, "haha");
序列化 后 变成 :
{ "Id" : 110101, "Name" : "haha" }
这样的明文。当然,如果数据多的化,非常不清晰,因而需要一个 格式化 的过程。
变成:
{
"Id" : 110101,
"Name" : "haha"
}
总结一下:json序列化就是将内存中的(一类)数据转换为标准化的、格式化的明文。反序列化就是将明文转为内存中的(一类)数据。
Newtonsoft.Json 的序列化如下:
mate one = new mate(110101, "haha");
string single = Newtonsoft.Json.JsonConvert.SerializeObject(one);
List<mate> two = new List<mate>();
two.Add(new mate(110101, "baba"));
two.Add(new mate(110102, "mama"));
string family = Newtonsoft.Json.JsonConvert.SerializeObject(two);
Newtonsoft.Json 的反序列化则是:
mate oneFF = Newtonsoft.Json.JsonConvert.DeserializeObject<mate>(single);
List<mate> twoFF = Newtonsoft.Json.JsonConvert.DeserializeObject<List<mate>>(family);
3 Newtonsoft.Json 的小问题
Newtonsoft 的 json 组件在效率、可靠性等方面都无与伦比。
但也稍微有点问题:
(1)发布软件必须多带一个 Newtonsoft.Json.dll;不符合纯绿色软件的要求;
(2)不能自动格式化;或者需要另外加一个格式化代码;
4 无需 DLL 的轻量化json序列化与反序列化
一般的小工具,俺都喜欢写成纯绿色代码。
所以一直在使用自己的 json 序列化与反序列化组件,先开放出来共享。
没有DLL;自动格式化;可靠性与效率都OK。
4.1 轻量化json序列化与反序列化的源代码
using System;
using System.IO;
using System.Text;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization.Json;
/// <summary>
/// System.Runtime.Serialization.Json扩展方法类
/// ([DataContract]和[DataMember]联合使用来标记被序列化的字段)
/// </summary>
public static class SimpleJson
{
/// <summary>
/// 数据格式化的字典
/// </summary>
private static Dictionary<Type, DataContractJsonSerializer> dic { get; set; } = new Dictionary<Type, DataContractJsonSerializer>();
/// <summary>
/// TAB对应的空格数
/// </summary>
private static string TabString { get; set; } = " ";
/// <summary>
/// 检索合适的数据格式化的字典
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
private static DataContractJsonSerializer GetSerializer(Type type)
{
if (!dic.ContainsKey(type))
{
dic.Add(type, new DataContractJsonSerializer(type));
}
return dic[type];
}
/// <summary>
/// 将Json字符串反序列化为对象实例
/// System.Runtime.Serialization.Json
/// ([DataContract]和[DataMember]联合使用来标记被序列化的字段)
/// </summary>
/// <typeparam name="T">对象类型</typeparam>
/// <param name="jsonString">Json字符串</param>
/// <returns>对象实例</returns>
public static T DeserializeObject<T>(string jsonString)
{
DataContractJsonSerializer ser = GetSerializer(typeof(T));
using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(jsonString)))
{
T jsonObject = (T)ser.ReadObject(ms);
return jsonObject;
}
}
/// <summary>
/// 将对象实例序列化为Json字符串
/// System.Runtime.Serialization.Json
/// ([DataContract]和[DataMember]联合使用来标记被序列化的字段)
/// </summary>
/// <typeparam name="T">对象类型</typeparam>
/// <param name="obj">对象实例</param>
/// <returns>Json字符串</returns>
public static string SerializeObject<T>(T obj)
{
DataContractJsonSerializer ser = GetSerializer(typeof(T));
using (MemoryStream ms = new MemoryStream())
{
ser.WriteObject(ms, obj);
ms.Position = 0;
using (StreamReader sr = new StreamReader(ms, Encoding.UTF8))
{
return JsonFormat(sr.ReadToEnd());
}
}
}
/// <summary>
/// JSON字符串格式化
/// </summary>
/// <param name="json"></param>
/// <returns></returns>
public static string JsonFormat(string json)
{
int level = 0;
int bracket = 0;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < json.Length; i++)
{
string c = json.Substring(i, 1);
if (level > 0)
{
string tail = sb.ToString();
tail = tail.Substring(tail.Length - 1);
if (tail == "\n")
{
sb.Append(LevelSpace(level));
}
}
if (c == "\"")
{
if ((bracket % 2) == 0)
{
sb.Append(c);
bracket++;
continue;
}
else
{
if (json.Substring(i - 1, 1) == "\\")
{
sb.Append(c);
continue;
}
else
{
sb.Append(c);
bracket--;
continue;
}
}
}
if ((bracket % 2) == 1)
{
sb.Append(c);
continue;
}
switch (c)
{
case "{":
case "[":
sb.AppendLine(c);
level++;
break;
case ":":
sb.Append(c + " ");
break;
case ",":
sb.AppendLine(c);
break;
case "}":
case "]":
sb.AppendLine("");
level--;
sb.Append(LevelSpace(level) + c);
break;
default:
sb.Append(c);
break;
}
}
return sb.ToString();
}
/// <summary>
/// 按数据层次计算前端空格数(4=TAB)
/// </summary>
/// <param name="level"></param>
/// <returns></returns>
private static string LevelSpace(int level)
{
#if __ORIGINAL__
string leaf = string.Empty;
for (int t = 0; t < level; t++)
{
leaf += TabString;
}
return leaf;
#endif
string[] sa = new string[level];
for (int i = 0; i < sa.Length; i++) sa[i] = TabString;
return String.Join("", sa);
}
}
4.2 使用轻量化json序列化与反序列化
将上述代码保存为 SimpleJson.cs 文件,将该文件添加之项目。
其他就很简单了。
4.3 轻量化json序列化
// 将 cx 这个类的实例序列化为 json 字符串(自动格式化哦!)
string json = SimpleJson.SerializeObject(cx);
// 保存到文本文件;
File.WriteAllText(filename, json, Encoding.UTF8);
4.4 轻量化json反序列化的代码
// 文本文件读取配置信息 json
string json = File.ReadAllText(filename, Encoding.UTF8);
// 将json反序列化为 ConfigInfo 类的实例 cy
ConfigInfo cy = SimpleJson.DeserializeObject<ConfigInfo>(json);
4.5 可能遇到的问题
可能在这句上出现错误:
using System.Runtime.Serialization.Json;
解决之道:
需要添加 System.Runtime.Serialization 组件。
这个不会需要附加 DLL 文件哦。
没有违反纯绿色软件之约。