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

推荐订阅源

Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Hacker News - Newest:
Hacker News - Newest: "LLM"
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
L
LINUX DO - 最新话题
Cloudbric
Cloudbric
N
News and Events Feed by Topic
S
Secure Thoughts
Vercel News
Vercel News
S
Security @ Cisco Blogs
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
S
SegmentFault 最新的问题
Hacker News: Ask HN
Hacker News: Ask HN
博客园 - 聂微东
WordPress大学
WordPress大学
Google Online Security Blog
Google Online Security Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Google DeepMind News
Google DeepMind News
PCI Perspectives
PCI Perspectives
雷峰网
雷峰网
Hugging Face - Blog
Hugging Face - Blog
Blog — PlanetScale
Blog — PlanetScale
Apple Machine Learning Research
Apple Machine Learning Research
C
CXSECURITY Database RSS Feed - CXSecurity.com
T
Threat Research - Cisco Blogs
博客园 - 司徒正美
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
A
About on SuperTechFans
P
Proofpoint News Feed
大猫的无限游戏
大猫的无限游戏
V
V2EX
I
Intezer
H
Hacker News: Front Page
www.infosecurity-magazine.com
www.infosecurity-magazine.com
L
Lohrmann on Cybersecurity
F
Fortinet All Blogs
Schneier on Security
Schneier on Security
博客园 - 叶小钗
The Cloudflare Blog
月光博客
月光博客
W
WeLiveSecurity
T
Tenable Blog
P
Proofpoint News Feed
aimingoo的专栏
aimingoo的专栏
Help Net Security
Help Net Security
L
LangChain Blog
C
CERT Recently Published Vulnerability Notes
T
The Exploit Database - CXSecurity.com
美团技术团队
B
Blog

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


}
}