惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Hugging Face - Blog
Hugging Face - Blog
B
Blog
博客园_首页
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
G
GRAHAM CLULEY
Microsoft Azure Blog
Microsoft Azure Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
WordPress大学
WordPress大学
The GitHub Blog
The GitHub Blog
Security Latest
Security Latest
F
Full Disclosure
云风的 BLOG
云风的 BLOG
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
C
Cyber Attacks, Cyber Crime and Cyber Security
L
LINUX DO - 热门话题
V
Visual Studio Blog
有赞技术团队
有赞技术团队
腾讯CDC
V
V2EX
Vercel News
Vercel News
C
Cisco Blogs
V2EX - 技术
V2EX - 技术
Scott Helme
Scott Helme
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
AWS News Blog
AWS News Blog
S
Schneier on Security
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
小众软件
小众软件
G
Google Developers Blog
C
Check Point Blog
C
CERT Recently Published Vulnerability Notes
博客园 - 叶小钗
S
SegmentFault 最新的问题
T
Tor Project blog
J
Java Code Geeks
L
Lohrmann on Cybersecurity
Application and Cybersecurity Blog
Application and Cybersecurity Blog
T
The Exploit Database - CXSecurity.com
Apple Machine Learning Research
Apple Machine Learning Research
T
Tailwind CSS Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
博客园 - 司徒正美
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
S
Secure Thoughts
量子位
N
News and Events Feed by Topic
MyScale Blog
MyScale Blog
TaoSecurity Blog
TaoSecurity Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Engineering at Meta
Engineering at Meta

博客园 - 无名365

Provisioning 是什么意思? SOA与云计算 Good understand on WCF Data Contract & Serialization WCF DataContract EmitDefaultValue a xml configuration for unity and interception Programmatically Compress and Decompress Files using c# CodeRun Studio - A free cloud develop and debug service for .Net Cloud IDE 10个最“优秀”的代码注释 Compress and Decompress JQuery Mobile 1.0 Released, Gets Mixed Reaction Interceptor in Unity and Policy Injection in Unity Configuring Unity Container with Policy Injection Configuration Unity Configuration Node Unity Configuration from Separate Configuration File IoC and Unity - Configuration Objects and the Art of Data Modeling AppFabric Cache - Cache Cluster EF - How to delete an object without retrieving it LINQ to SQL Extension: Batch Deletion with Lambda Expression
.NET 2.0 JSON Parser
无名365 · 2013-06-14 · via 博客园 - 无名365

2013-06-14 23:30  无名365  阅读(401)  评论()    收藏  举报

A simple pure .Net 2.0 Library for JSON parser -- JSON-Sharp

using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using System.Collections;
using System.Globalization;
using System.Text.RegularExpressions;
using System.Diagnostics;
using System.IO;
using System.Collections.Specialized;
using System.Web.UI;


namespace JsonSharp
{
public enum JSONSerializationMode
{
/// <summary>
/// Slower, but takes advantage of overriden ToJSON methods
/// </summary>
UseReflection,
/// <summary>
/// Faster, but ignores overriden ToJSON methods
/// </summary>
NoReflection
};
/// <summary>
/// This class encodes and decodes JSON strings.
/// </summary>
public static class JSON
{
/// <summary>
/// Converts the public Properties of any object to a JSON-encoded string. Uses reflection to take advantaget of overridden ToJSON methods
/// </summary>
/// <returns>JSON-encoded string</returns>
public static string ToJSON(object obj)
{
if (obj == null)
return "null";

return ToJSON(obj, JSONSerializationMode.UseReflection);
}

public static string ToJSON(object obj, JSONSerializationMode mode)
{
if (obj == null)
return "null";

if (mode == JSONSerializationMode.UseReflection)
{
Type type = obj.GetType();
MethodInfo[] methods = type.GetMethods();
MethodInfo method = null;
foreach (var mi in methods)
{
if (mi.Name == "ToJSON" && mi.ReturnType == typeof(string) 
&& mi.DeclaringType == type && mi.GetParameters().Length == 0)
{
method = mi;
break;
}
}
//methods = methods.Where(c => c.Name == "ToJSON" && c.ReturnType == typeof(string)).ToArray();
//MethodInfo method = methods.SingleOrDefault(c => c.DeclaringType == type && c.GetParameters().Length == 0);

if (method != null)
return (string)method.Invoke(obj, new object[0]);
}

return JSON.Serialize(obj, mode);
}

public static string EscapeString(string obj)
{
return obj.Replace("\\", "\\\\").Replace("/", "\\/").Replace("\"", "\\\"")
.Replace("\b", "\\b").Replace("\f", "\\f").Replace("\n", "\\n")
.Replace("\r", "\\r").Replace("\t", "\\t");
}

public static string UnescapeString(string obj)
{
if (!obj.Contains("\\"))
return obj;

return obj.Replace("\\t", "\t").Replace("\\r", "\r").Replace("\\n", "\n")
.Replace("\\f", "\f").Replace("\\b", "\b").Replace("\\\"", "\"")
.Replace("\\/", "/").Replace("\\\\", "\\");

}

public static string Serialize(object obj)
{
return Serialize(obj, JSONSerializationMode.UseReflection);
}

public static string Serialize(object obj, JSONSerializationMode mode)
{
if (obj == null)
return "null";

Type type = obj.GetType();

if (IsNumeric(type))
{
return obj.ToString();
}
else if (type == typeof(string) || type == typeof(char))
{
return "\"" + EscapeString("" + obj) + "\"";
}
else if (type == typeof(bool))
{
bool x = (bool)obj;

return x ? "true" : "false";
}
else if (type == typeof(DateTime))
{
DateTime dt = (DateTime)obj;

return "\"" + dt.ToString("MM/dd/yyyy hh:mm:ss tt") + "\"";
}

StringBuilder result = new StringBuilder();

if (obj.GetType().IsArray)
{
result.Append("[");

Array array = (Array)obj;

foreach (object value in array)
{
result.Append(ToJSON(value,mode) + ",");
}

string json = result.ToString();

if (json.EndsWith(","))
json = json.Substring(0, json.Length - 1);

json += "]";

return json;
}
else if (obj is IDictionary)
{
IDictionary d = (IDictionary)obj;
IDictionaryEnumerator i = d.GetEnumerator();

result.Append("{");

while (i.MoveNext())
{
result.Append("\"" + i.Key + "\":");
result.Append(ToJSON(i.Value,mode));
result.Append(",");
}

string json = result.ToString();

if (json.EndsWith(","))
json = json.Substring(0, json.Length - 1);

json += "}";

return json;
}
else if (obj is NameValueCollection)
{
NameValueCollection col = (NameValueCollection)obj;

result.Append("{");

for (int i = 0; i < col.Count; i++)
{
string key = col.Keys[i];
string value = col[key];

result.Append("\"" + key + "\":");
result.Append(ToJSON(value,mode));
result.Append(",");
}

string json = result.ToString();

if (json.EndsWith(","))
json = json.Substring(0, json.Length - 1);

json += "}";

return json;
}
else if (obj is IEnumerable)
{
IEnumerable item = (IEnumerable)obj;
IEnumerator i = item.GetEnumerator();

result.Append("[");

while (i.MoveNext())
{
result.Append(ToJSON(i.Current,mode) + ",");
}

string json = result.ToString();

if (json.EndsWith(","))
json = json.Substring(0, json.Length - 1);

json += "]";

return json;

}
else
{
result.Append("{");

PropertyInfo[] props = obj.GetType().GetProperties();


foreach (PropertyInfo prop in props)
{
if (IgnoreProperty(prop))
continue;

object value = prop.GetValue(obj, null);

result.Append("\"" + prop.Name + "\":");
result.Append(ToJSON(prop.GetValue(obj, null),mode));
result.Append(",");
}

string json = result.ToString();

if (json.EndsWith(","))
json = json.Substring(0, json.Length - 1);

json += "}";

return json;
}
}

private static bool IgnoreProperty(PropertyInfo prop)
{
if (prop.GetIndexParameters().Length > 0)
return true;

string Namespace = prop.PropertyType.Namespace;

if (Namespace != null && (Namespace.StartsWith("System.Reflection") || Namespace.StartsWith("System.Security")))
return true;

Type[] ignoredTypes = new Type[] { typeof(Type), typeof(HtmlTextWriter), typeof(TextWriter), typeof(Stream) };

foreach (Type type in ignoredTypes)
{
if (prop.PropertyType == type || prop.PropertyType.IsSubclassOf(type))
return true;
}

return false;
}

/// <summary>
/// Parses a JSON string into the specified object type
/// </summary>
/// <param name="json">The JSON-encoded string you want to deserialize</param>
/// <param name="type">The object type you want your json string deserialized into</param>
/// <returns>Object of type Type</returns>
public static object Deserialize(string json, Type type)
{
object o = Deserialize(json);
PropertyCache.Clear();
ConstructorCache.Clear();
return Deserialize(o, type);
}

public static T Deserialize<T>(string json)
{
return (T)Deserialize(json, typeof(T));
}

private static Hashtable PropertyCache = new Hashtable();
private static Hashtable ConstructorCache = new Hashtable();
private static Hashtable PropCanWrite = new Hashtable();

private static object Deserialize(object obj, Type type)
{
if (obj == null)
return null;

Type t = obj.GetType();

if (t == typeof(ArrayList))
{
if (type.IsArray)
type = type.GetElementType();

ArrayList elems = new ArrayList();

foreach (object o in (ArrayList)obj)
{
if (o != null)
elems.Add(Deserialize(o, type));
}

return elems.ToArray(type);
}

if (t == typeof(Hashtable))
{
Hashtable hash = (Hashtable)obj;
PropertyInfo[] props;
ConstructorInfo construct;

if (PropertyCache.ContainsKey(type))
{
props = (PropertyInfo[])PropertyCache[type];
construct = (ConstructorInfo)ConstructorCache[type];
}
else
{
props = type.GetProperties();
PropertyCache[type] = props;

construct = type.GetConstructor(new Type[] { });
ConstructorCache[type] = construct;
}

object elem = construct.Invoke(new object[] { });

foreach (PropertyInfo prop in props)
{
if (!prop.CanWrite)
continue;

object temp = hash[prop.Name];

if (temp == null)
temp = hash[prop.Name.ToLower()];

if (temp == null)
temp = hash[char.ToLower(prop.Name[0]) + prop.Name.Substring(1)];

if (temp != null)
prop.SetValue(elem, Deserialize(temp, prop.PropertyType), null);
}

return elem;
}

if (obj is double)
{
double val = (double)obj;

if (type == typeof(int))
return (int)val;
else if (type == typeof(short))
return (short)val;
else if (type == typeof(decimal))
return (decimal)val;
else if (type == typeof(long))
return (long)val;
else if (type == typeof(double))
return (double)val;
else if (type == typeof(float))
return (float)val;
else if (type == typeof(byte))
return (byte)val;
else
return val;
}

if (type == typeof(bool))
{
return (bool)obj;
}

if (type == typeof(string))
return obj.ToString();

if (type == typeof(DateTime))
{
DateTime outdt;

if (DateTime.TryParse(obj.ToString(), out outdt))
return outdt;
else
return new DateTime(1, 1, 1);
}

if (type == typeof(object))
return obj;

return null;
}

private static double outDouble = 0;

public static object Deserialize(string json)
{
JSONDeserializer jd = new JSONDeserializer(json);
return jd.Deserialize();
}

//This is just a test
private class JSONTypeDeserializer
{
private string json;
private Type type;
private int index;

public JSONTypeDeserializer(string json, Type type)
{
this.json = json;
this.type = type;
}

public object Deserialize()
{
index = 0;

if (type.IsArray)
{
var t = type.GetElementType();
return ProcessArray(t);

}
else
{
return ProcessHash(type);
}
}

private object ProcessValue(Type type)
{
SkipWhitespace();

if (json[index] == '[')
{
if (json == "[]")
return new object[0];

return ProcessArray(type);
}

if (json[index] == '{')
{
if (json == "{}")
{
ConstructorInfo constructor = type.GetConstructor(new Type[0]);

if (constructor != null)
return constructor.Invoke(new object[0]);
else
return null;
}

return ProcessHash(type);
}

if (json[index] == '"')
{
string val = UnescapeString(ProcessString());

DateTime outDate;

if (DateTime.TryParse(val, out outDate))
{
return outDate;
}

return val;
}

int startIndex = index;

while (index < json.Length && json[index] != ',' && json[index] != '}' && json[index] != ']' && !Char.IsWhiteSpace(json[index]))
index++;

string jval = json.Substring(startIndex, index - startIndex).Trim();

if (jval == "true")
return true;

if (jval == "false")
return false;

if (jval == "null")
return null;

if (type == typeof(int))
return int.Parse(jval);
else if (type == typeof(short))
return short.Parse(jval);
else if (type == typeof(decimal))
return decimal.Parse(jval);
else if (type == typeof(long))
return long.Parse(jval);
else if (type == typeof(double))
return double.Parse(jval);
else if (type == typeof(float))
return float.Parse(jval);

return null;
}

private object[] ProcessArray(Type type)
{
index++;

List<object> list = new List<object>();

while (true)
{
SkipWhitespace();

list.Add(ProcessValue(type));

if (!MoveNext())
break;
}

return list.ToArray();
}

private object ProcessHash(Type type)
{
ConstructorInfo constructor = type.GetConstructor(new Type[0]);

object obj;

if (constructor != null)
obj = constructor.Invoke(new object[0]);
else
return null;

index++;

PropertyInfo[] props = type.GetProperties();

Type t;

while (true)
{
SkipWhitespace();

string key = ProcessHashKey().Trim();
SkipWhitespace();

//PropertyInfo prop = props.FirstOrDefault(c => c.Name == key);
PropertyInfo prop = null;
foreach (var p in props)
{
if (p.Name == key)
{
prop = p;
break;
}
}

if (prop == null)
{
//prop = props.FirstOrDefault(c => c.Name.ToLower() == key.ToLower());
foreach (var p in props)
{
if (p.Name.ToLower() == key.ToLower())
{
prop = p;
break;
}
}
}

if (prop == null)
t = typeof(object);
else
t = prop.PropertyType;

object value = ProcessValue(t);

prop.SetValue(obj, value, null);

if (!MoveNext())
break;
}

return obj;
}

private bool MoveNext()
{
while (index < json.Length && json[index] != ',' &&
json[index] != ']' && json[index] != '}')
index++;

if (index >= json.Length)
return false;

if (json[index] == ']' || json[index] == '}')
{
index++;
return false;
}

index++;

SkipWhitespace();

if (index >= json.Length)
return false;

return true;
}

private void SkipWhitespace()
{
while (index < json.Length && Char.IsWhiteSpace(json[index]))
index++;
}

private string ProcessHashKey()
{
int startIndex = index;
while (json[index++] != ':')
;
string result = json.Substring(startIndex, index - startIndex - 1).Trim();
result = ChopStart(result,"\"");
result = ChopEnd(result,"\"");
return result;
}

private string ProcessString()
{
int startIndex = index;
StringBuilder result = new StringBuilder();

while (true)
{
index++;

while (json[index] != '"')
{
result.Append(json[index]);
index++;
}

int j = index - 1;
int count = 0;

while (json[j] == '\\')
{
j--;
count++;
}

//if there are an even number of backslashes, 
//then they are all just backslashes and they aren't escaping the quote
//otherwise, the quote is being escaped and we need to keep searching for the close quote
if (count % 2 == 0)
break;
else
result.Append(json[index]);
}

return result.ToString();
}


}

private class JSONDeserializer
{
private string json;
private int index;

public JSONDeserializer(string JSON)
{
index = 0;
json = JSON;
}

public object Deserialize()
{
index = 0;
SkipWhitespace();
return ProcessValue();
}

private object ProcessValue()
{
if (json[index] == '[')
{
return ProcessArray();
}

if (json[index] == '{')
{
return ProcessHash();
}

if (json[index] == '"')
{
string val = UnescapeString(ProcessString());

//DateTime outDate;

//if (DateTime.TryParse(val, out outDate))
//{
// return outDate;
//}

return val;
}

int startIndex = index;

while (index < json.Length && json[index] != ',' && json[index] != '}' && json[index] != ']' && !Char.IsWhiteSpace(json[index]))
index++;

string jval = json.Substring(startIndex, index - startIndex);

if (jval == "true")
return true;

if (jval == "false")
return false;

if (jval == "null")
return null;

if (double.TryParse(jval, out outDouble))
return outDouble;

return null;
}

private ArrayList ProcessArray()
{
index++;

ArrayList list = new ArrayList();

SkipWhitespace();

if (json[index] == ']')
{
index++;
return list;
}

while (true)
{

list.Add(ProcessValue());

if (!MoveNext())
break;
}

return list;
}

private Hashtable ProcessHash()
{
index++;

Hashtable hash = new Hashtable();

SkipWhitespace();

if (json[index] == '}')
{
index++;
return hash;
}

while (true)
{
string key = ProcessHashKey();

SkipWhitespace();

object value = ProcessValue();

hash.Add(key, value);

if (!MoveNext())
break;
}

return hash;
}

private bool MoveNext()
{
while (index < json.Length && json[index] != ',' &&
json[index] != ']' && json[index] != '}')
index++;

if (index >= json.Length)
return false;

if (json[index] == ']' || json[index] == '}')
{
index++;
return false;
}

index++;

SkipWhitespaceEnd();

if (index >= json.Length)
return false;

return true;
}

private void SkipWhitespaceEnd()
{
while (index < json.Length && Char.IsWhiteSpace(json[index]))
index++;
}

private void SkipWhitespace()
{
while (Char.IsWhiteSpace(json[index]))
index++;
}

private string ProcessHashKey()
{
int startIndex = index + 1;
while (json[index++] != ':')
;
string result = json.Substring(startIndex, index - startIndex - 2).TrimEnd();
return result;
}

private string ProcessString()
{
int startIndex = index + 1;

while (true)
{
index++;

while (json[index] != '"')
index++;

int j = index - 1;
int count = 0;

while (json[j] == '\\')
{
j--;
count++;
}

//if there are an even number of backslashes, 
//then they are all just backslashes and they aren't escaping the quote
//otherwise, the quote is being escaped and we need to keep searching for the close quote
if (count % 2 == 0)
break;
}

return json.Substring(startIndex, index - startIndex);
}

}

private static string ChopStart(string str, string x)
{
if (str.StartsWith(x))
return str.Substring(x.Length);

return str;
}

private static string ChopEnd(string str, string x)
{
if (str.EndsWith(x))
return str.Substring(0, str.Length - x.Length);

return str;
}

private static bool IsNumeric(Type type)
{
Type[] types = new Type[]{
typeof(int), typeof(short), typeof(long),
typeof(double), typeof(decimal), typeof(byte)};

foreach (var t in types)
{
if (t == type)
{
return true;
}
}

return false;
//return types.Contains(type);
}


}
}