Files
Yi.Framework/Yi.Furion.Net6/Yi.Framework.Infrastructure/Helper/JsonHelper.cs
2023-04-15 17:35:22 +08:00

519 lines
19 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System;
using System.Collections.Generic;
using System.Text.Json;
namespace Yi.Framework.Infrastructure.Helper
{
public class JsonHelper
{
public static string ObjToStr<T>(T obj, string dateTimeFormat)
{
IsoDateTimeConverter timeConverter = new IsoDateTimeConverter()
{
DateTimeFormat = dateTimeFormat
};
return JsonConvert.SerializeObject(obj, Formatting.Indented, timeConverter);
}
public static string ObjToStr<T>(T obj)
{
return JsonConvert.SerializeObject(obj);
}
public static T StrToObj<T>(string str)
{
return JsonConvert.DeserializeObject<T>(str)!;
}
/// <summary>
/// 转换对象为JSON格式数据
/// </summary>
/// <typeparam name="T">类</typeparam>
/// <param name="obj">对象</param>
/// <returns>字符格式的JSON数据</returns>
public static string GetJSON<T>(object obj)
{
string result = string.Empty;
try
{
System.Text.Json.JsonSerializer.Serialize("");
System.Runtime.Serialization.Json.DataContractJsonSerializer serializer =
new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(T));
using (MemoryStream ms = new MemoryStream())
{
serializer.WriteObject(ms, obj);
result = System.Text.Encoding.UTF8.GetString(ms.ToArray());
}
}
catch (Exception)
{
throw;
}
return result;
}
/// <summary>
/// 转换List<T>的数据为JSON格式
/// </summary>
/// <typeparam name="T">类</typeparam>
/// <param name="vals">列表值</param>
/// <returns>JSON格式数据</returns>
public string JSON<T>(List<T> vals)
{
System.Text.StringBuilder st = new System.Text.StringBuilder();
try
{
System.Runtime.Serialization.Json.DataContractJsonSerializer s = new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(T));
foreach (T city in vals)
{
using (MemoryStream ms = new MemoryStream())
{
s.WriteObject(ms, city);
st.Append(System.Text.Encoding.UTF8.GetString(ms.ToArray()));
}
}
}
catch (Exception)
{
}
return st.ToString();
}
/// <summary>
/// JSON格式字符转换为T类型的对象
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="jsonStr"></param>
/// <returns></returns>
public static T ParseFormByJson<T>(string jsonStr)
{
T obj = Activator.CreateInstance<T>();
using (MemoryStream ms =
new MemoryStream(System.Text.Encoding.UTF8.GetBytes(jsonStr)))
{
System.Runtime.Serialization.Json.DataContractJsonSerializer serializer =
new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(T));
return (T)serializer.ReadObject(ms)!;
}
}
public string JSON1<SendData>(List<SendData> vals)
{
System.Text.StringBuilder st = new System.Text.StringBuilder();
try
{
System.Runtime.Serialization.Json.DataContractJsonSerializer s = new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(SendData));
foreach (SendData city in vals)
{
using (MemoryStream ms = new MemoryStream())
{
s.WriteObject(ms, city);
st.Append(System.Text.Encoding.UTF8.GetString(ms.ToArray()));
}
}
}
catch (Exception)
{
}
return st.ToString();
}
private static bool IsJsonStart(ref string json)
{
if (!string.IsNullOrEmpty(json))
{
json = json.Trim('\r', '\n', ' ');
if (json.Length > 1)
{
char s = json[0];
char e = json[json.Length - 1];
return s == '{' && e == '}' || s == '[' && e == ']';
}
}
return false;
}
public static bool IsJson(string json)
{
int errIndex;
return IsJson(json, out errIndex);
}
public static bool IsJson(string json, out int errIndex)
{
errIndex = 0;
if (IsJsonStart(ref json))
{
CharState cs = new CharState();
char c;
for (int i = 0; i < json.Length; i++)
{
c = json[i];
if (SetCharState(c, ref cs) && cs.childrenStart)//设置关键符号状态。
{
string item = json.Substring(i);
int err;
int length = GetValueLength(item, true, out err);
cs.childrenStart = false;
if (err > 0)
{
errIndex = i + err;
return false;
}
i = i + length - 1;
}
if (cs.isError)
{
errIndex = i;
return false;
}
}
return !cs.arrayStart && !cs.jsonStart;
}
return false;
}
/// <summary>
/// 获取值的长度当Json值嵌套以"{"或"["开头时)
/// </summary>
private static int GetValueLength(string json, bool breakOnErr, out int errIndex)
{
errIndex = 0;
int len = 0;
if (!string.IsNullOrEmpty(json))
{
CharState cs = new CharState();
char c;
for (int i = 0; i < json.Length; i++)
{
c = json[i];
if (!SetCharState(c, ref cs))//设置关键符号状态。
{
if (!cs.jsonStart && !cs.arrayStart)//json结束又不是数组则退出。
{
break;
}
}
else if (cs.childrenStart)//正常字符,值状态下。
{
int length = GetValueLength(json.Substring(i), breakOnErr, out errIndex);//递归子值,返回一个长度。。。
cs.childrenStart = false;
cs.valueStart = 0;
//cs.state = 0;
i = i + length - 1;
}
if (breakOnErr && cs.isError)
{
errIndex = i;
return i;
}
if (!cs.jsonStart && !cs.arrayStart)//记录当前结束位置。
{
len = i + 1;//长度比索引+1
break;
}
}
}
return len;
}
/// <summary>
/// 设置字符状态(返回true则为关键词返回false则当为普通字符处理
/// </summary>
private static bool SetCharState(char c, ref CharState cs)
{
cs.CheckIsError(c);
switch (c)
{
case '{'://[{ "[{A}]":[{"[{B}]":3,"m":"C"}]}]
#region
if (cs.keyStart <= 0 && cs.valueStart <= 0)
{
cs.keyStart = 0;
cs.valueStart = 0;
if (cs.jsonStart && cs.state == 1)
{
cs.childrenStart = true;
}
else
{
cs.state = 0;
}
cs.jsonStart = true;//开始。
return true;
}
#endregion
break;
case '}':
#region
if (cs.keyStart <= 0 && cs.valueStart < 2 && cs.jsonStart)
{
cs.jsonStart = false;//正常结束。
cs.state = 0;
cs.keyStart = 0;
cs.valueStart = 0;
cs.setDicValue = true;
return true;
}
// cs.isError = !cs.jsonStart && cs.state == 0;
#endregion
break;
case '[':
#region
if (!cs.jsonStart)
{
cs.arrayStart = true;
return true;
}
else if (cs.jsonStart && cs.state == 1)
{
cs.childrenStart = true;
return true;
}
#endregion
break;
case ']':
#region
if (cs.arrayStart && !cs.jsonStart && cs.keyStart <= 2 && cs.valueStart <= 0)//[{},333]//这样结束。
{
cs.keyStart = 0;
cs.valueStart = 0;
cs.arrayStart = false;
return true;
}
#endregion
break;
case '"':
case '\'':
#region
if (cs.jsonStart || cs.arrayStart)
{
if (cs.state == 0)//key阶段,有可能是数组["aa",{}]
{
if (cs.keyStart <= 0)
{
cs.keyStart = c == '"' ? 3 : 2;
return true;
}
else if (cs.keyStart == 2 && c == '\'' || cs.keyStart == 3 && c == '"')
{
if (!cs.escapeChar)
{
cs.keyStart = -1;
return true;
}
else
{
cs.escapeChar = false;
}
}
}
else if (cs.state == 1 && cs.jsonStart)//值阶段必须是Json开始了。
{
if (cs.valueStart <= 0)
{
cs.valueStart = c == '"' ? 3 : 2;
return true;
}
else if (cs.valueStart == 2 && c == '\'' || cs.valueStart == 3 && c == '"')
{
if (!cs.escapeChar)
{
cs.valueStart = -1;
return true;
}
else
{
cs.escapeChar = false;
}
}
}
}
#endregion
break;
case ':':
#region
if (cs.jsonStart && cs.keyStart < 2 && cs.valueStart < 2 && cs.state == 0)
{
if (cs.keyStart == 1)
{
cs.keyStart = -1;
}
cs.state = 1;
return true;
}
// cs.isError = !cs.jsonStart || (cs.keyStart < 2 && cs.valueStart < 2 && cs.state == 1);
#endregion
break;
case ',':
#region //["aa",{aa:12,}]
if (cs.jsonStart)
{
if (cs.keyStart < 2 && cs.valueStart < 2 && cs.state == 1)
{
cs.state = 0;
cs.keyStart = 0;
cs.valueStart = 0;
//if (cs.valueStart == 1)
//{
// cs.valueStart = 0;
//}
cs.setDicValue = true;
return true;
}
}
else if (cs.arrayStart && cs.keyStart <= 2)
{
cs.keyStart = 0;
//if (cs.keyStart == 1)
//{
// cs.keyStart = -1;
//}
return true;
}
#endregion
break;
case ' ':
case '\r':
case '\n'://[ "a",\r\n{} ]
case '\0':
case '\t':
if (cs.keyStart <= 0 && cs.valueStart <= 0) //cs.jsonStart &&
{
return true;//跳过空格。
}
break;
default: //值开头。。
if (c == '\\') //转义符号
{
if (cs.escapeChar)
{
cs.escapeChar = false;
}
else
{
cs.escapeChar = true;
return true;
}
}
else
{
cs.escapeChar = false;
}
if (cs.jsonStart || cs.arrayStart) // Json 或数组开始了。
{
if (cs.keyStart <= 0 && cs.state == 0)
{
cs.keyStart = 1;//无引号的
}
else if (cs.valueStart <= 0 && cs.state == 1 && cs.jsonStart)//只有Json开始才有值。
{
cs.valueStart = 1;//无引号的
}
}
break;
}
return false;
}
}
/// <summary>
/// 字符状态
/// </summary>
public class CharState
{
internal bool jsonStart = false;//以 "{"开始了...
internal bool setDicValue = false;// 可以设置字典值了。
internal bool escapeChar = false;//以"\"转义符号开始了
/// <summary>
/// 数组开始【仅第一开头才算】值嵌套的以【childrenStart】来标识。
/// </summary>
internal bool arrayStart = false;//以"[" 符号开始了
internal bool childrenStart = false;//子级嵌套开始了。
/// <summary>
/// 【0 初始状态,或 遇到“,”逗号】【1 遇到“:”冒号】
/// </summary>
internal int state = 0;
/// <summary>
/// 【-1 取值结束】【0 未开始】【1 无引号开始】【2 单引号开始】【3 双引号开始】
/// </summary>
internal int keyStart = 0;
/// <summary>
/// 【-1 取值结束】【0 未开始】【1 无引号开始】【2 单引号开始】【3 双引号开始】
/// </summary>
internal int valueStart = 0;
internal bool isError = false;//是否语法错误。
internal void CheckIsError(char c)//只当成一级处理因为GetLength会递归到每一个子项处理
{
if (keyStart > 1 || valueStart > 1)
{
return;
}
//示例 ["aa",{"bbbb":123,"fff","ddd"}]
switch (c)
{
case '{'://[{ "[{A}]":[{"[{B}]":3,"m":"C"}]}]
isError = jsonStart && state == 0;//重复开始错误 同时不是值处理。
break;
case '}':
isError = !jsonStart || keyStart != 0 && state == 0;//重复结束错误 或者 提前结束{"aa"}。正常的有{}
break;
case '[':
isError = arrayStart && state == 0;//重复开始错误
break;
case ']':
isError = !arrayStart || jsonStart;//重复开始错误 或者 Json 未结束
break;
case '"':
case '\'':
isError = !(jsonStart || arrayStart); //json 或数组开始。
if (!isError)
{
//重复开始 [""",{"" "}]
isError = state == 0 && keyStart == -1 || state == 1 && valueStart == -1;
}
if (!isError && arrayStart && !jsonStart && c == '\'')//['aa',{}]
{
isError = true;
}
break;
case ':':
isError = !jsonStart || state == 1;//重复出现。
break;
case ',':
isError = !(jsonStart || arrayStart); //json 或数组开始。
if (!isError)
{
if (jsonStart)
{
isError = state == 0 || state == 1 && valueStart > 1;//重复出现。
}
else if (arrayStart)//["aa,] [,] [{},{}]
{
isError = keyStart == 0 && !setDicValue;
}
}
break;
case ' ':
case '\r':
case '\n'://[ "a",\r\n{} ]
case '\0':
case '\t':
break;
default: //值开头。。
isError = !jsonStart && !arrayStart || state == 0 && keyStart == -1 || valueStart == -1 && state == 1;//
break;
}
//if (isError)
//{
//}
}
}
}