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

推荐订阅源

Google DeepMind News
Google DeepMind News
Martin Fowler
Martin Fowler
Google DeepMind News
Google DeepMind News
大猫的无限游戏
大猫的无限游戏
雷峰网
雷峰网
MyScale Blog
MyScale Blog
G
GRAHAM CLULEY
云风的 BLOG
云风的 BLOG
MongoDB | Blog
MongoDB | Blog
WordPress大学
WordPress大学
Y
Y Combinator Blog
The Register - Security
The Register - Security
宝玉的分享
宝玉的分享
S
Schneier on Security
N
News and Events Feed by Topic
T
Threat Research - Cisco Blogs
C
Cyber Attacks, Cyber Crime and Cyber Security
G
Google Developers Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园_首页
S
Security @ Cisco Blogs
H
Hackread – Cybersecurity News, Data Breaches, AI and More
V
Visual Studio Blog
M
MIT News - Artificial intelligence
U
Unit 42
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
人人都是产品经理
人人都是产品经理
W
WeLiveSecurity
Latest news
Latest news
博客园 - 【当耐特】
P
Palo Alto Networks Blog
博客园 - 叶小钗
Simon Willison's Weblog
Simon Willison's Weblog
Jina AI
Jina AI
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
T
Troy Hunt's Blog
L
LangChain Blog
腾讯CDC
Microsoft Azure Blog
Microsoft Azure Blog
博客园 - Franky
C
Check Point Blog
O
OpenAI News
C
Cisco Blogs
T
Tor Project blog
A
About on SuperTechFans
F
Full Disclosure
D
Darknet – Hacking Tools, Hacker News & Cyber Security
L
Lohrmann on Cybersecurity
Attack and Defense Labs
Attack and Defense Labs

博客园 - 无名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);
}


}
}