diff --git a/NewLife.Core/NewLife.Core.csproj b/NewLife.Core/NewLife.Core.csproj
index d840da7..a441e3d 100644
--- a/NewLife.Core/NewLife.Core.csproj
+++ b/NewLife.Core/NewLife.Core.csproj
@@ -164,6 +164,12 @@
<Compile Include="Reflection\AttributeX.cs" />
<Compile Include="Reflection\快速反射\ConstructorInfoX.cs" />
<Compile Include="Reflection\EmitHelper.cs" />
+ <Compile Include="Serialization\Json\IJsonHost.cs" />
+ <Compile Include="Serialization\Json\Json.cs" />
+ <Compile Include="Serialization\Json\JsonComposite.cs" />
+ <Compile Include="Serialization\Json\JsonDictionary.cs" />
+ <Compile Include="Serialization\Json\JsonGeneral.cs" />
+ <Compile Include="Serialization\Json\JsonArray.cs" />
<Compile Include="Serialization\Json\IJson.cs" />
<Compile Include="Serialization\Protocol.cs">
<SubType>Code</SubType>
diff --git a/NewLife.Core/Serialization/Json/IJson.cs b/NewLife.Core/Serialization/Json/IJson.cs
index 6e4ae40..c64efc7 100644
--- a/NewLife.Core/Serialization/Json/IJson.cs
+++ b/NewLife.Core/Serialization/Json/IJson.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.Reflection;
using System.Text;
using System.Web.Script.Serialization;
@@ -8,302 +9,63 @@ using NewLife.Reflection;
namespace NewLife.Serialization
{
- /// <summary>Json序列化接口</summary>
- public interface IJson
+ /// <summary>IJson序列化接口</summary>
+ public interface IJson : IFormatterX
{
- /// <summary>写入对象,得到Json字符串</summary>
- /// <param name="value"></param>
- /// <param name="indented">是否缩进</param>
- /// <returns></returns>
- String Write(Object value, Boolean indented = false);
-
- /// <summary>从Json字符串中读取对象</summary>
- /// <param name="json"></param>
- /// <param name="type"></param>
- /// <returns></returns>
- Object Read(String json, Type type);
- }
-
- /// <summary>Json助手</summary>
- public static class JsonHelper
- {
- /// <summary>默认实现</summary>
- public static IJson Default { get; set; }
+ #region 属性
+ /// <summary>是否缩进</summary>
+ Boolean Indented { get; set; }
- static JsonHelper()
- {
- if (JsonNet.Support())
- Default = new JsonNet();
- else
- Default = new JsonDefault();
- }
+ /// <summary>处理器列表</summary>
+ IList<IJsonHandler> Handlers { get; }
+ #endregion
- /// <summary>写入对象,得到Json字符串</summary>
+ #region 写入
+ /// <summary>写入字符串</summary>
/// <param name="value"></param>
- /// <param name="indented">是否缩进</param>
- /// <returns></returns>
- public static String ToJson(this Object value, Boolean indented = false)
- {
- return Default.Write(value, indented);
- }
-
- /// <summary>从Json字符串中读取对象</summary>
- /// <param name="json"></param>
- /// <param name="type"></param>
- /// <returns></returns>
- public static Object ToJsonEntity(this String json, Type type)
- {
- return Default.Read(json, type);
- }
-
- /// <summary>从Json字符串中读取对象</summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="json"></param>
- /// <returns></returns>
- public static T ToJsonEntity<T>(this String json)
- {
- return (T)Default.Read(json, typeof(T));
- }
- }
-
- class JsonDefault : IJson
- {
- //static JsonDefault()
- //{
- // // 用XmlIgnore特性作为忽略属性的方法
- // var src = typeof(JavaScriptSerializer).GetMethodEx("CheckScriptIgnoreAttribute");
- // var dst = typeof(JsonDefault).GetMethodEx("CheckScriptIgnoreAttribute");
- // if (src != null && dst != null)
- // {
- // //new JavaScriptSerializer().Invoke(src, src);
- // //new JsonDefault().CheckScriptIgnoreAttribute(dst);
- // ApiHook.ReplaceMethod(src, dst);
- // }
- //}
-
- private bool CheckScriptIgnoreAttribute(MemberInfo memberInfo)
- {
- if (memberInfo.IsDefined(typeof(ScriptIgnoreAttribute), true)) return true;
- if (memberInfo.IsDefined(typeof(XmlIgnoreAttribute), true)) return true;
-
- return false;
- }
-
- #region IJson 成员
- public String Write(Object value, Boolean indented)
- {
- var json = new JavaScriptSerializer().Serialize(value);
- //if (indented) json = Process(json);
- if (indented) json = FormatOutput(json);
-
- return json;
- }
-
- public Object Read(String json, Type type)
- {
- // 如果有必要,可以实现JavaScriptTypeResolver,然后借助Type.GetTypeEx得到更强的反射类型能力
- return new JavaScriptSerializer().Deserialize(json, type);
- }
+ void Write(String value);
- //static String Process(String inputText)
- //{
- // bool escaped = false;
- // bool inquotes = false;
- // int column = 0;
- // int indentation = 0;
- // var indentations = new Stack<int>();
- // int TABBING = 8;
- // var sb = new StringBuilder();
- // foreach (char x in inputText)
- // {
- // sb.Append(x);
- // column++;
- // if (escaped)
- // {
- // escaped = false;
- // }
- // else
- // {
- // if (x == '\\')
- // {
- // escaped = true;
- // }
- // else if (x == '\"')
- // {
- // inquotes = !inquotes;
- // }
- // else if (!inquotes)
- // {
- // if (x == ',')
- // {
- // // if we see a comma, go to next line, and indent to the same depth
- // sb.Append("\r\n");
- // column = 0;
- // for (int i = 0; i < indentation; i++)
- // {
- // sb.Append(" ");
- // column++;
- // }
- // }
- // else if (x == '[' || x == '{')
- // {
- // // if we open a bracket or brace, indent further (push on stack)
- // indentations.Push(indentation);
- // indentation = column;
- // }
- // else if (x == ']' || x == '}')
- // {
- // // if we close a bracket or brace, undo one level of indent (pop)
- // indentation = indentations.Pop();
- // }
- // else if (x == ':')
- // {
- // // if we see a colon, add spaces until we get to the next
- // // tab stop, but without using tab characters!
- // while ((column % TABBING) != 0)
- // {
- // sb.Append(' ');
- // column++;
- // }
- // }
- // }
- // }
- // }
- // return sb.ToString();
- //}
-
- static String FormatOutput(String json)
- {
- var sb = new StringBuilder();
-
- bool escaping = false;
- bool inQuotes = false;
- int indentation = 0;
+ void Write(StringBuilder sb, Object value);
+ #endregion
- foreach (char ch in json)
- {
- if (escaping)
- {
- escaping = false;
- sb.Append(ch);
- }
- else
- {
- if (ch == '\\')
- {
- escaping = true;
- sb.Append(ch);
- }
- else if (ch == '\"')
- {
- inQuotes = !inQuotes;
- sb.Append(ch);
- }
- else if (!inQuotes)
- {
- if (ch == ',')
- {
- sb.Append(ch);
- sb.Append("\r\n");
- sb.Append('\t', indentation);
- }
- else if (ch == '[' || ch == '{')
- {
- sb.Append(ch);
- sb.Append("\r\n");
- sb.Append('\t', ++indentation);
- }
- else if (ch == ']' || ch == '}')
- {
- sb.Append("\r\n");
- sb.Append('\t', --indentation);
- sb.Append(ch);
- }
- else if (ch == ':')
- {
- sb.Append(ch);
- sb.Append('\t');
- }
- else
- {
- sb.Append(ch);
- }
- }
- else
- {
- sb.Append(ch);
- }
- }
- }
+ #region 读取
+ Boolean Read(String value);
- return sb.ToString();
- }
+ /// <summary>读取字节</summary>
+ /// <returns></returns>
+ Byte ReadByte();
#endregion
}
- class JsonNet : IJson
+ /// <summary>IJson读写处理器接口</summary>
+ public interface IJsonHandler : IHandler<IJson>
{
- private static Type _Convert;
- private static Type _Formatting;
- private static Object _Set;
- static JsonNet()
- {
- var type = "Newtonsoft.Json.JsonConvert".GetTypeEx();
- if (type != null)
- {
- _Convert = type;
- _Formatting = "Newtonsoft.Json.Formatting".GetTypeEx();
- type = "Newtonsoft.Json.JsonSerializerSettings".GetTypeEx();
-
- // 忽略循环引用
- _Set = type.CreateInstance();
- if (_Set != null) _Set.SetValue("ReferenceLoopHandling", 1);
-
- // 自定义IContractResolver,用XmlIgnore特性作为忽略属性的方法
- var sc = ScriptEngine.Create(_code, false);
- sc.Compile();
- if (sc.Method != null)
- {
- _Set.SetValue("ContractResolver", sc.Method.DeclaringType.CreateInstance());
- }
-
- if (XTrace.Debug) XTrace.WriteLine("使用Json.Net,位于 {0}", _Convert.Assembly.Location);
- }
- }
-
- private const String _code = @"
-class MyContractResolver : Newtonsoft.Json.Serialization.DefaultContractResolver
-{
- protected override Newtonsoft.Json.Serialization.JsonProperty CreateProperty(MemberInfo member, Newtonsoft.Json.MemberSerialization memberSerialization)
- {
- if (member.GetCustomAttribute<System.Xml.Serialization.XmlIgnoreAttribute>() != null) return null;
-
- return base.CreateProperty(member, memberSerialization);
+ /// <summary>获取对象的Json字符串表示形式。</summary>
+ /// <param name="value"></param>
+ /// <returns>返回null表示不支持</returns>
+ String GetString(Object value);
}
- public static void Main() { }
-}";
- /// <summary>是否支持</summary>
- /// <returns></returns>
- public static Boolean Support() { return _Convert != null; }
-
- #region IJson 成员
- public String Write(Object value, Boolean indented)
+ /// <summary>IJson读写处理器基类</summary>
+ public abstract class JsonHandlerBase : HandlerBase<IJson, IJsonHandler>, IJsonHandler
+ {
+ /// <summary>获取对象的Json字符串表示形式。</summary>
+ /// <param name="value"></param>
+ /// <returns>返回null表示不支持</returns>
+ public abstract String GetString(Object value);
+
+ /// <summary>写入一个对象</summary>
+ /// <param name="value">目标对象</param>
+ /// <param name="type">类型</param>
+ /// <returns>是否处理成功</returns>
+ public override Boolean Write(Object value, Type type)
{
- // 忽略循环引用
- //var set = _Set.CreateInstance();
- //if (set != null) set.SetValue("ReferenceLoopHandling", 1);
+ var v = GetString(value);
+ if (v == null) return false;
- if (!indented)
- return (String)_Convert.Invoke("SerializeObject", value, _Set);
- else
- return (String)_Convert.Invoke("SerializeObject", value, Enum.ToObject(_Formatting, 1), _Set);
- }
+ Host.Write(v);
- public Object Read(String json, Type type)
- {
- return _Convert.Invoke("DeserializeObject", json, type);
+ return true;
}
- #endregion
}
}
\ No newline at end of file
diff --git a/NewLife.Core/Serialization/Json/IJsonHost.cs b/NewLife.Core/Serialization/Json/IJsonHost.cs
new file mode 100644
index 0000000..0d77868
--- /dev/null
+++ b/NewLife.Core/Serialization/Json/IJsonHost.cs
@@ -0,0 +1,309 @@
+using System;
+using System.Reflection;
+using System.Text;
+using System.Web.Script.Serialization;
+using System.Xml.Serialization;
+using NewLife.Log;
+using NewLife.Reflection;
+
+namespace NewLife.Serialization
+{
+ /// <summary>Json序列化接口</summary>
+ public interface IJsonHost
+ {
+ /// <summary>写入对象,得到Json字符串</summary>
+ /// <param name="value"></param>
+ /// <param name="indented">是否缩进</param>
+ /// <returns></returns>
+ String Write(Object value, Boolean indented = false);
+
+ /// <summary>从Json字符串中读取对象</summary>
+ /// <param name="json"></param>
+ /// <param name="type"></param>
+ /// <returns></returns>
+ Object Read(String json, Type type);
+ }
+
+ /// <summary>Json助手</summary>
+ public static class JsonHelper
+ {
+ /// <summary>默认实现</summary>
+ public static IJsonHost Default { get; set; }
+
+ static JsonHelper()
+ {
+ if (JsonNet.Support())
+ Default = new JsonNet();
+ else
+ Default = new JsonDefault();
+ }
+
+ /// <summary>写入对象,得到Json字符串</summary>
+ /// <param name="value"></param>
+ /// <param name="indented">是否缩进</param>
+ /// <returns></returns>
+ public static String ToJson(this Object value, Boolean indented = false)
+ {
+ return Default.Write(value, indented);
+ }
+
+ /// <summary>从Json字符串中读取对象</summary>
+ /// <param name="json"></param>
+ /// <param name="type"></param>
+ /// <returns></returns>
+ public static Object ToJsonEntity(this String json, Type type)
+ {
+ return Default.Read(json, type);
+ }
+
+ /// <summary>从Json字符串中读取对象</summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="json"></param>
+ /// <returns></returns>
+ public static T ToJsonEntity<T>(this String json)
+ {
+ return (T)Default.Read(json, typeof(T));
+ }
+ }
+
+ class JsonDefault : IJsonHost
+ {
+ //static JsonDefault()
+ //{
+ // // 用XmlIgnore特性作为忽略属性的方法
+ // var src = typeof(JavaScriptSerializer).GetMethodEx("CheckScriptIgnoreAttribute");
+ // var dst = typeof(JsonDefault).GetMethodEx("CheckScriptIgnoreAttribute");
+ // if (src != null && dst != null)
+ // {
+ // //new JavaScriptSerializer().Invoke(src, src);
+ // //new JsonDefault().CheckScriptIgnoreAttribute(dst);
+ // ApiHook.ReplaceMethod(src, dst);
+ // }
+ //}
+
+ private bool CheckScriptIgnoreAttribute(MemberInfo memberInfo)
+ {
+ if (memberInfo.IsDefined(typeof(ScriptIgnoreAttribute), true)) return true;
+ if (memberInfo.IsDefined(typeof(XmlIgnoreAttribute), true)) return true;
+
+ return false;
+ }
+
+ #region IJsonHost 成员
+ public String Write(Object value, Boolean indented)
+ {
+ var json = new JavaScriptSerializer().Serialize(value);
+ //if (indented) json = Process(json);
+ if (indented) json = FormatOutput(json);
+
+ return json;
+ }
+
+ public Object Read(String json, Type type)
+ {
+ // 如果有必要,可以实现JavaScriptTypeResolver,然后借助Type.GetTypeEx得到更强的反射类型能力
+ return new JavaScriptSerializer().Deserialize(json, type);
+ }
+
+ //static String Process(String inputText)
+ //{
+ // bool escaped = false;
+ // bool inquotes = false;
+ // int column = 0;
+ // int indentation = 0;
+ // var indentations = new Stack<int>();
+ // int TABBING = 8;
+ // var sb = new StringBuilder();
+ // foreach (char x in inputText)
+ // {
+ // sb.Append(x);
+ // column++;
+ // if (escaped)
+ // {
+ // escaped = false;
+ // }
+ // else
+ // {
+ // if (x == '\\')
+ // {
+ // escaped = true;
+ // }
+ // else if (x == '\"')
+ // {
+ // inquotes = !inquotes;
+ // }
+ // else if (!inquotes)
+ // {
+ // if (x == ',')
+ // {
+ // // if we see a comma, go to next line, and indent to the same depth
+ // sb.Append("\r\n");
+ // column = 0;
+ // for (int i = 0; i < indentation; i++)
+ // {
+ // sb.Append(" ");
+ // column++;
+ // }
+ // }
+ // else if (x == '[' || x == '{')
+ // {
+ // // if we open a bracket or brace, indent further (push on stack)
+ // indentations.Push(indentation);
+ // indentation = column;
+ // }
+ // else if (x == ']' || x == '}')
+ // {
+ // // if we close a bracket or brace, undo one level of indent (pop)
+ // indentation = indentations.Pop();
+ // }
+ // else if (x == ':')
+ // {
+ // // if we see a colon, add spaces until we get to the next
+ // // tab stop, but without using tab characters!
+ // while ((column % TABBING) != 0)
+ // {
+ // sb.Append(' ');
+ // column++;
+ // }
+ // }
+ // }
+ // }
+ // }
+ // return sb.ToString();
+ //}
+
+ static String FormatOutput(String json)
+ {
+ var sb = new StringBuilder();
+
+ bool escaping = false;
+ bool inQuotes = false;
+ int indentation = 0;
+
+ foreach (char ch in json)
+ {
+ if (escaping)
+ {
+ escaping = false;
+ sb.Append(ch);
+ }
+ else
+ {
+ if (ch == '\\')
+ {
+ escaping = true;
+ sb.Append(ch);
+ }
+ else if (ch == '\"')
+ {
+ inQuotes = !inQuotes;
+ sb.Append(ch);
+ }
+ else if (!inQuotes)
+ {
+ if (ch == ',')
+ {
+ sb.Append(ch);
+ sb.Append("\r\n");
+ sb.Append('\t', indentation);
+ }
+ else if (ch == '[' || ch == '{')
+ {
+ sb.Append(ch);
+ sb.Append("\r\n");
+ sb.Append('\t', ++indentation);
+ }
+ else if (ch == ']' || ch == '}')
+ {
+ sb.Append("\r\n");
+ sb.Append('\t', --indentation);
+ sb.Append(ch);
+ }
+ else if (ch == ':')
+ {
+ sb.Append(ch);
+ sb.Append('\t');
+ }
+ else
+ {
+ sb.Append(ch);
+ }
+ }
+ else
+ {
+ sb.Append(ch);
+ }
+ }
+ }
+
+ return sb.ToString();
+ }
+ #endregion
+ }
+
+ class JsonNet : IJsonHost
+ {
+ private static Type _Convert;
+ private static Type _Formatting;
+ private static Object _Set;
+ static JsonNet()
+ {
+ var type = "Newtonsoft.Json.JsonConvert".GetTypeEx();
+ if (type != null)
+ {
+ _Convert = type;
+ _Formatting = "Newtonsoft.Json.Formatting".GetTypeEx();
+ type = "Newtonsoft.Json.JsonSerializerSettings".GetTypeEx();
+
+ // 忽略循环引用
+ _Set = type.CreateInstance();
+ if (_Set != null) _Set.SetValue("ReferenceLoopHandling", 1);
+
+ // 自定义IContractResolver,用XmlIgnore特性作为忽略属性的方法
+ var sc = ScriptEngine.Create(_code, false);
+ sc.Compile();
+ if (sc.Method != null)
+ {
+ _Set.SetValue("ContractResolver", sc.Method.DeclaringType.CreateInstance());
+ }
+
+ if (XTrace.Debug) XTrace.WriteLine("使用Json.Net,位于 {0}", _Convert.Assembly.Location);
+ }
+ }
+
+ private const String _code = @"
+class MyContractResolver : Newtonsoft.Json.Serialization.DefaultContractResolver
+{
+ protected override Newtonsoft.Json.Serialization.JsonProperty CreateProperty(MemberInfo member, Newtonsoft.Json.MemberSerialization memberSerialization)
+ {
+ if (member.GetCustomAttribute<System.Xml.Serialization.XmlIgnoreAttribute>() != null) return null;
+
+ return base.CreateProperty(member, memberSerialization);
+ }
+ public static void Main() { }
+}";
+
+ /// <summary>是否支持</summary>
+ /// <returns></returns>
+ public static Boolean Support() { return _Convert != null; }
+
+ #region IJsonHost 成员
+ public String Write(Object value, Boolean indented)
+ {
+ // 忽略循环引用
+ //var set = _Set.CreateInstance();
+ //if (set != null) set.SetValue("ReferenceLoopHandling", 1);
+
+ if (!indented)
+ return (String)_Convert.Invoke("SerializeObject", value, _Set);
+ else
+ return (String)_Convert.Invoke("SerializeObject", value, Enum.ToObject(_Formatting, 1), _Set);
+ }
+
+ public Object Read(String json, Type type)
+ {
+ return _Convert.Invoke("DeserializeObject", json, type);
+ }
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/NewLife.Core/Serialization/Json/Json.cs b/NewLife.Core/Serialization/Json/Json.cs
new file mode 100644
index 0000000..ccc5727
--- /dev/null
+++ b/NewLife.Core/Serialization/Json/Json.cs
@@ -0,0 +1,197 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Reflection;
+using System.Text;
+using NewLife.Log;
+using NewLife.Reflection;
+
+namespace NewLife.Serialization
+{
+ /// <summary>Json序列化</summary>
+ public class Json : FormatterBase, IJson
+ {
+ #region 属性
+ /// <summary>是否缩进</summary>
+ public Boolean Indented { get; set; }
+
+ /// <summary>处理器列表</summary>
+ public IList<IJsonHandler> Handlers { get; private set; }
+
+ //private StringBuilder _builder;
+ #endregion
+
+ #region 构造
+ /// <summary>实例化</summary>
+ public Json()
+ {
+ UseProperty = true;
+
+ //_builder = new StringBuilder();
+
+ // 遍历所有处理器实现
+ var list = new List<IJsonHandler>();
+ list.Add(new JsonGeneral { Host = this });
+ list.Add(new JsonComposite { Host = this });
+ list.Add(new JsonArray { Host = this });
+ //list.Add(new JsonDictionary { Host = this });
+ // 根据优先级排序
+ list.Sort();
+
+ Handlers = list;
+ }
+ #endregion
+
+ #region 处理器
+ /// <summary>添加处理器</summary>
+ /// <param name="handler"></param>
+ /// <returns></returns>
+ public Json AddHandler(IJsonHandler handler)
+ {
+ if (handler != null)
+ {
+ handler.Host = this;
+ Handlers.Add(handler);
+ // 根据优先级排序
+ (Handlers as List<IJsonHandler>).Sort();
+ }
+
+ return this;
+ }
+
+ /// <summary>添加处理器</summary>
+ /// <typeparam name="THandler"></typeparam>
+ /// <param name="priority"></param>
+ /// <returns></returns>
+ public Json AddHandler<THandler>(Int32 priority = 0) where THandler : IJsonHandler, new()
+ {
+ var handler = new THandler();
+ handler.Host = this;
+ if (priority != 0) handler.Priority = priority;
+
+ return AddHandler(handler);
+ }
+
+ /// <summary>获取处理器</summary>
+ /// <typeparam name="T"></typeparam>
+ /// <returns></returns>
+ public T GetHandler<T>() where T : class, IJsonHandler
+ {
+ foreach (var item in Handlers)
+ {
+ if (item is T) return item as T;
+ }
+
+ return default(T);
+ }
+ #endregion
+
+ #region 写入
+ /// <summary>写入一个对象</summary>
+ /// <param name="value">目标对象</param>
+ /// <param name="type">类型</param>
+ /// <returns></returns>
+ [DebuggerHidden]
+ public virtual Boolean Write(Object value, Type type = null)
+ {
+ if (type == null)
+ {
+ if (value == null) return true;
+
+ type = value.GetType();
+
+ // 一般类型为空是顶级调用
+ if (Hosts.Count == 0) WriteLog("JsonWrite {0} {1}", type.Name, value);
+ }
+
+ //foreach (var item in Handlers)
+ //{
+ // if (item.Write(value, type)) return true;
+ //}
+
+ var sb = new StringBuilder();
+ Write(sb, value);
+
+ Stream.Write(sb.ToString().GetBytes());
+
+ return false;
+ }
+
+ /// <summary>写入字符串</summary>
+ /// <param name="value"></param>
+ public virtual void Write(String value)
+ {
+ //_builder.Append(value);
+ }
+
+ public virtual void Write(StringBuilder sb, Object value)
+ {
+ if (value == null) return;
+ var type = value.GetType();
+
+ foreach (var item in Handlers)
+ {
+ if (item.Write(value, type)) return;
+ }
+ }
+ #endregion
+
+ #region 读取
+ /// <summary>读取指定类型对象</summary>
+ /// <param name="type"></param>
+ /// <returns></returns>
+ [DebuggerHidden]
+ public virtual Object Read(Type type)
+ {
+ var value = type.CreateInstance();
+ if (!TryRead(type, ref value)) throw new Exception("读取失败!");
+
+ return value;
+ }
+
+ /// <summary>读取指定类型对象</summary>
+ /// <typeparam name="T"></typeparam>
+ /// <returns></returns>
+ [DebuggerHidden]
+ public T Read<T>()
+ {
+ return (T)(Object)Read(typeof(T));
+ }
+
+ /// <summary>尝试读取指定类型对象</summary>
+ /// <param name="type"></param>
+ /// <param name="value"></param>
+ /// <returns></returns>
+ [DebuggerHidden]
+ public virtual Boolean TryRead(Type type, ref Object value)
+ {
+ if (Hosts.Count == 0) WriteLog("JsonRead {0} {1}", type.Name, value);
+
+ foreach (var item in Handlers)
+ {
+ if (item.TryRead(type, ref value)) return true;
+ }
+ return false;
+ }
+
+ public virtual Boolean Read(String value)
+ {
+ return true;
+ }
+
+ /// <summary>读取字节</summary>
+ /// <returns></returns>
+ public virtual Byte ReadByte()
+ {
+ var b = Stream.ReadByte();
+ if (b < 0) throw new Exception("数据流超出范围!");
+ return (Byte)b;
+ }
+ #endregion
+
+ #region 辅助函数
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/NewLife.Core/Serialization/Json/JsonArray.cs b/NewLife.Core/Serialization/Json/JsonArray.cs
new file mode 100644
index 0000000..25b6c4b
--- /dev/null
+++ b/NewLife.Core/Serialization/Json/JsonArray.cs
@@ -0,0 +1,124 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using NewLife.Reflection;
+using System.Linq;
+
+namespace NewLife.Serialization
+{
+ /// <summary>列表数据编码</summary>
+ public class JsonArray : JsonHandlerBase
+ {
+ /// <summary>初始化</summary>
+ public JsonArray()
+ {
+ // 优先级
+ Priority = 20;
+ }
+
+ /// <summary>获取对象的Json字符串表示形式。</summary>
+ /// <param name="value"></param>
+ /// <returns>返回null表示不支持</returns>
+ public override String GetString(Object value)
+ {
+ if (value == null) return String.Empty;
+
+ var type = value.GetType();
+ if (type == typeof(Guid)) return ((Guid)value).ToString();
+ if (type == typeof(Byte[])) return Convert.ToBase64String((Byte[])value);
+ if (type == typeof(Char[])) return new String((Char[])value);
+
+ switch (Type.GetTypeCode(value.GetType()))
+ {
+ case TypeCode.Boolean:
+ return value + "";
+ case TypeCode.Byte:
+ case TypeCode.SByte:
+ case TypeCode.Char:
+ return value + "";
+ case TypeCode.DBNull:
+ case TypeCode.Empty:
+ return String.Empty;
+ case TypeCode.DateTime:
+ return value + "";
+ case TypeCode.Decimal:
+ return value + "";
+ case TypeCode.Single:
+ case TypeCode.Double:
+ return value + "";
+ case TypeCode.Int16:
+ case TypeCode.Int32:
+ case TypeCode.Int64:
+ case TypeCode.UInt16:
+ case TypeCode.UInt32:
+ case TypeCode.UInt64:
+ return value + "";
+ case TypeCode.String:
+ if (((String)value).IsNullOrEmpty()) return String.Empty;
+ return "\"{0}\"".F(value);
+ case TypeCode.Object:
+ default:
+ return null;
+ }
+ }
+
+ /// <summary>写入</summary>
+ /// <param name="value"></param>
+ /// <param name="type"></param>
+ /// <returns></returns>
+ public override bool Write(object value, Type type)
+ {
+ if (!typeof(IList).IsAssignableFrom(type)) return false;
+
+ var list = value as IList;
+
+ Host.Write("[");
+ if (list != null && list.Count > 0)
+ {
+ // 循环写入数据
+ foreach (var item in list)
+ {
+ Host.Write(item);
+ }
+ }
+ Host.Write("]");
+
+ return true;
+ }
+
+ /// <summary>读取</summary>
+ /// <param name="type"></param>
+ /// <param name="value"></param>
+ /// <returns></returns>
+ public override bool TryRead(Type type, ref object value)
+ {
+ if (!typeof(IList).IsAssignableFrom(type)) return false;
+
+ // 先读取
+ if (!Host.Read("[")) return false;
+
+ // 子元素类型
+ var elmType = type.GetElementTypeEx();
+
+ var list = typeof(IList<>).MakeGenericType(elmType).CreateInstance() as IList;
+ while (!Host.Read("]"))
+ {
+ Object obj = null;
+ if (!Host.TryRead(elmType, ref obj)) return false;
+
+ list.Add(obj);
+ }
+
+ // 数组的创建比较特别
+ if (typeof(Array).IsAssignableFrom(type))
+ {
+ value = Array.CreateInstance(type.GetElementTypeEx(), list.Count);
+ list.CopyTo((Array)value, 0);
+ }
+ else
+ value = list;
+
+ return true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/NewLife.Core/Serialization/Json/JsonComposite.cs b/NewLife.Core/Serialization/Json/JsonComposite.cs
new file mode 100644
index 0000000..d528958
--- /dev/null
+++ b/NewLife.Core/Serialization/Json/JsonComposite.cs
@@ -0,0 +1,281 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Xml.Serialization;
+using NewLife.Collections;
+using NewLife.Reflection;
+
+namespace NewLife.Serialization
+{
+ /// <summary>复合对象处理器</summary>
+ public class JsonComposite : JsonHandlerBase
+ {
+ /// <summary>要忽略的成员</summary>
+ public ICollection<String> IgnoreMembers { get; set; }
+
+ /// <summary>实例化</summary>
+ public JsonComposite()
+ {
+ Priority = 100;
+
+ //IgnoreMembers = new HashSet<String>(StringComparer.OrdinalIgnoreCase);
+ IgnoreMembers = new HashSet<String>();
+ }
+
+ /// <summary>获取对象的Json字符串表示形式。</summary>
+ /// <param name="value"></param>
+ /// <returns>返回null表示不支持</returns>
+ public override String GetString(Object value)
+ {
+ if (value == null) return String.Empty;
+
+ var type = value.GetType();
+ if (type == typeof(Guid)) return ((Guid)value).ToString();
+ if (type == typeof(Byte[])) return Convert.ToBase64String((Byte[])value);
+ if (type == typeof(Char[])) return new String((Char[])value);
+
+ switch (Type.GetTypeCode(value.GetType()))
+ {
+ case TypeCode.Boolean:
+ return value + "";
+ case TypeCode.Byte:
+ case TypeCode.SByte:
+ case TypeCode.Char:
+ return value + "";
+ case TypeCode.DBNull:
+ case TypeCode.Empty:
+ return String.Empty;
+ case TypeCode.DateTime:
+ return value + "";
+ case TypeCode.Decimal:
+ return value + "";
+ case TypeCode.Single:
+ case TypeCode.Double:
+ return value + "";
+ case TypeCode.Int16:
+ case TypeCode.Int32:
+ case TypeCode.Int64:
+ case TypeCode.UInt16:
+ case TypeCode.UInt32:
+ case TypeCode.UInt64:
+ return value + "";
+ case TypeCode.String:
+ if (((String)value).IsNullOrEmpty()) return String.Empty;
+ return "\"{0}\"".F(value);
+ case TypeCode.Object:
+ default:
+ return null;
+ }
+ }
+
+ /// <summary>写入对象</summary>
+ /// <param name="value">目标对象</param>
+ /// <param name="type">类型</param>
+ /// <returns></returns>
+ public override Boolean Write(Object value, Type type)
+ {
+ if (value == null) return false;
+
+ // 不支持基本类型
+ if (Type.GetTypeCode(type) != TypeCode.Object) return false;
+
+ var ms = GetMembers(type);
+ WriteLog("JsonWrite类{0} 共有成员{1}个", type.Name, ms.Count);
+
+ Host.Hosts.Push(value);
+
+ // 获取成员
+ foreach (var member in ms)
+ {
+ if (IgnoreMembers != null && IgnoreMembers.Contains(member.Name)) continue;
+
+ var mtype = GetMemberType(member);
+ Host.Member = member;
+
+ var v = value.GetValue(member);
+ WriteLog(" {0}.{1} {2}", type.Name, member.Name, v);
+
+ if (!Host.Write(v, mtype))
+ {
+ Host.Hosts.Pop();
+ return false;
+ }
+ }
+ Host.Hosts.Pop();
+
+ return true;
+ }
+
+ /// <summary>尝试读取指定类型对象</summary>
+ /// <param name="type"></param>
+ /// <param name="value"></param>
+ /// <returns></returns>
+ public override Boolean TryRead(Type type, ref Object value)
+ {
+ if (type == null)
+ {
+ if (value == null) return false;
+ type = value.GetType();
+ }
+
+ // 不支持基本类型
+ if (Type.GetTypeCode(type) != TypeCode.Object) return false;
+ // 不支持基类不是Object的特殊类型
+ //if (type.BaseType != typeof(Object)) return false;
+ if (!typeof(Object).IsAssignableFrom(type)) return false;
+
+ var ms = GetMembers(type);
+ WriteLog("JsonRead类{0} 共有成员{1}个", type.Name, ms.Count);
+
+ if (value == null) value = type.CreateInstance();
+
+ Host.Hosts.Push(value);
+
+ // 成员序列化访问器
+ var ac = value as IMemberAccessor;
+
+ // 获取成员
+ for (int i = 0; i < ms.Count; i++)
+ {
+ var member = ms[i];
+ if (IgnoreMembers != null && IgnoreMembers.Contains(member.Name)) continue;
+
+ var mtype = GetMemberType(member);
+ Host.Member = member;
+ WriteLog(" {0}.{1}", member.DeclaringType.Name, member.Name);
+
+ // 成员访问器优先
+ if (ac != null)
+ {
+ // 访问器直接写入成员
+ if (ac.Read(Host, member))
+ {
+ // 访问器内部可能直接操作Hosts修改了父级对象,典型应用在于某些类需要根据某个字段值决定采用哪个派生类
+ var obj = Host.Hosts.Peek();
+ if (obj != value)
+ {
+ value = obj;
+ ms = GetMembers(value.GetType());
+ ac = value as IMemberAccessor;
+ }
+
+ continue;
+ }
+ }
+
+ Object v = null;
+ if (!Host.TryRead(mtype, ref v))
+ {
+ Host.Hosts.Pop();
+ return false;
+ }
+
+ value.SetValue(member, v);
+ }
+ Host.Hosts.Pop();
+
+ return true;
+ }
+
+ #region 获取成员
+ /// <summary>获取成员</summary>
+ /// <param name="type"></param>
+ /// <param name="baseFirst"></param>
+ /// <returns></returns>
+ protected virtual List<MemberInfo> GetMembers(Type type, Boolean baseFirst = true)
+ {
+ if (Host.UseProperty)
+ return GetProperties(type, baseFirst).Cast<MemberInfo>().ToList();
+ else
+ return GetFields(type, baseFirst).Cast<MemberInfo>().ToList();
+ }
+
+ private static DictionaryCache<Type, List<FieldInfo>> _cache1 = new DictionaryCache<Type, List<FieldInfo>>();
+ private static DictionaryCache<Type, List<FieldInfo>> _cache2 = new DictionaryCache<Type, List<FieldInfo>>();
+ /// <summary>获取字段</summary>
+ /// <param name="type"></param>
+ /// <param name="baseFirst"></param>
+ /// <returns></returns>
+ protected static List<FieldInfo> GetFields(Type type, Boolean baseFirst = true)
+ {
+ if (baseFirst)
+ return _cache1.GetItem(type, key => GetFields2(key, true));
+ else
+ return _cache2.GetItem(type, key => GetFields2(key, false));
+ }
+
+ static List<FieldInfo> GetFields2(Type type, Boolean baseFirst = true)
+ {
+ var list = new List<FieldInfo>();
+
+ // Void*的基类就是null
+ if (type == typeof(Object) || type.BaseType == null) return list;
+
+ if (baseFirst) list.AddRange(GetFields(type.BaseType));
+
+ var fis = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
+ foreach (var fi in fis)
+ {
+ if (fi.GetCustomAttribute<NonSerializedAttribute>() != null) continue;
+
+ list.Add(fi);
+ }
+
+ if (!baseFirst) list.AddRange(GetFields(type.BaseType));
+
+ return list;
+ }
+
+ private static DictionaryCache<Type, List<PropertyInfo>> _cache3 = new DictionaryCache<Type, List<PropertyInfo>>();
+ private static DictionaryCache<Type, List<PropertyInfo>> _cache4 = new DictionaryCache<Type, List<PropertyInfo>>();
+ /// <summary>获取属性</summary>
+ /// <param name="type"></param>
+ /// <param name="baseFirst"></param>
+ /// <returns></returns>
+ protected static List<PropertyInfo> GetProperties(Type type, Boolean baseFirst = true)
+ {
+ if (baseFirst)
+ return _cache3.GetItem(type, key => GetProperties2(key, true));
+ else
+ return _cache4.GetItem(type, key => GetProperties2(key, false));
+ }
+
+ static List<PropertyInfo> GetProperties2(Type type, Boolean baseFirst = true)
+ {
+ var list = new List<PropertyInfo>();
+
+ // Void*的基类就是null
+ if (type == typeof(Object) || type.BaseType == null) return list;
+
+ if (baseFirst) list.AddRange(GetProperties(type.BaseType));
+
+ var pis = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
+ foreach (var pi in pis)
+ {
+ if (pi.GetIndexParameters().Length > 0) continue;
+ if (pi.GetCustomAttribute<XmlIgnoreAttribute>() != null) continue;
+
+ list.Add(pi);
+ }
+
+ if (!baseFirst) list.AddRange(GetProperties(type.BaseType));
+
+ return list;
+ }
+
+ static Type GetMemberType(MemberInfo member)
+ {
+ switch (member.MemberType)
+ {
+ case MemberTypes.Field:
+ return (member as FieldInfo).FieldType;
+ case MemberTypes.Property:
+ return (member as PropertyInfo).PropertyType;
+ default:
+ throw new NotSupportedException();
+ }
+ }
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/NewLife.Core/Serialization/Json/JsonDictionary.cs b/NewLife.Core/Serialization/Json/JsonDictionary.cs
new file mode 100644
index 0000000..1e21ca4
--- /dev/null
+++ b/NewLife.Core/Serialization/Json/JsonDictionary.cs
@@ -0,0 +1,10 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace NewLife.Serialization
+{
+ class JsonDictionary
+ {
+ }
+}
diff --git a/NewLife.Core/Serialization/Json/JsonGeneral.cs b/NewLife.Core/Serialization/Json/JsonGeneral.cs
new file mode 100644
index 0000000..29161bf
--- /dev/null
+++ b/NewLife.Core/Serialization/Json/JsonGeneral.cs
@@ -0,0 +1,96 @@
+using System;
+using NewLife.Reflection;
+using System.Collections;
+using System.Collections.Generic;
+using System.Text;
+using System.Xml.Serialization;
+
+namespace NewLife.Serialization
+{
+ /// <summary>Json基础类型处理器</summary>
+ public class JsonGeneral : JsonHandlerBase
+ {
+ /// <summary>实例化</summary>
+ public JsonGeneral()
+ {
+ Priority = 10;
+ }
+
+ /// <summary>获取对象的Json字符串表示形式。</summary>
+ /// <param name="value"></param>
+ /// <returns>返回null表示不支持</returns>
+ public override String GetString(Object value)
+ {
+ if (value == null) return String.Empty;
+
+ var type = value.GetType();
+ if (type == typeof(Guid)) return ((Guid)value).ToString();
+ if (type == typeof(Byte[])) return Convert.ToBase64String((Byte[])value);
+ if (type == typeof(Char[])) return new String((Char[])value);
+
+ switch (Type.GetTypeCode(value.GetType()))
+ {
+ case TypeCode.Boolean:
+ return value + "";
+ case TypeCode.Byte:
+ case TypeCode.SByte:
+ case TypeCode.Char:
+ return value + "";
+ case TypeCode.DBNull:
+ case TypeCode.Empty:
+ return String.Empty;
+ case TypeCode.DateTime:
+ return value + "";
+ case TypeCode.Decimal:
+ return value + "";
+ case TypeCode.Single:
+ case TypeCode.Double:
+ return value + "";
+ case TypeCode.Int16:
+ case TypeCode.Int32:
+ case TypeCode.Int64:
+ case TypeCode.UInt16:
+ case TypeCode.UInt32:
+ case TypeCode.UInt64:
+ return value + "";
+ case TypeCode.String:
+ if (((String)value).IsNullOrEmpty()) return String.Empty;
+ return "\"{0}\"".F(value);
+ case TypeCode.Object:
+ default:
+ return null;
+ }
+ }
+
+ /// <summary>尝试读取指定类型对象</summary>
+ /// <param name="type"></param>
+ /// <param name="value"></param>
+ /// <returns></returns>
+ public override Boolean TryRead(Type type, ref Object value)
+ {
+ if (type == null)
+ {
+ if (value == null) return false;
+ type = value.GetType();
+ }
+
+ //if (type == typeof(Guid))
+ //{
+ // value = new Guid(ReadBytes(16));
+ // return true;
+ //}
+ //else if (type == typeof(Byte[]))
+ //{
+ // value = ReadBytes(-1);
+ // return true;
+ //}
+ //else if (type == typeof(Char[]))
+ //{
+ // value = ReadChars(-1);
+ // return true;
+ //}
+
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Test/Program.cs b/Test/Program.cs
index 38ff7fc..7dfcaea 100644
--- a/Test/Program.cs
+++ b/Test/Program.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
+using System.Text;
using System.Threading;
using System.Xml.Serialization;
using NewLife.Common;
@@ -104,16 +105,16 @@ namespace Test
static void Test4()
{
- //var buf = "41-54-0d-0d-0a-0d-0a-4F-4B-0d-0a".ToHex();
- //Console.WriteLine(buf.ToHex());
- //Console.WriteLine(buf.ToStr());
- //MQTest.TestBase();
+ var user = UserX.FindAll()[0];
+ Console.WriteLine(user);
- var ns = new Int32[] { 123, 0, -456, Int32.MinValue, Int32.MaxValue };
- foreach (var item in ns)
- {
- Console.WriteLine("{0}\t{1}\t{2}\t{3}\t{4}", item, (UInt32)item, (Int64)(UInt32)item, (Int64)item, (UInt64)item);
- }
+ var sb = new StringBuilder();
+
+ var json = new Json();
+ json.Log = XTrace.Log;
+ json.Write(sb, user);
+
+ Console.WriteLine(sb.ToString());
}
static void Test5()