forked from ln-dotnet/ln.json
WIP
parent
659088b90e
commit
b65cfd952e
|
@ -0,0 +1,45 @@
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
namespace sharp.json
|
||||||
|
{
|
||||||
|
public class FileBackedJSONValue<T>
|
||||||
|
{
|
||||||
|
public string FileName { get; set; }
|
||||||
|
public DateTime LoadedWriteTime { get; set; }
|
||||||
|
|
||||||
|
T current;
|
||||||
|
JSON jsource;
|
||||||
|
|
||||||
|
public FileBackedJSONValue(string filename)
|
||||||
|
{
|
||||||
|
FileName = filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T CurrentValue {
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (!File.Exists(FileName)){
|
||||||
|
current = default(T);
|
||||||
|
} else if ((current == null) || (File.GetLastWriteTime(FileName) != LoadedWriteTime))
|
||||||
|
{
|
||||||
|
jsource = JSON.ReadFrom(FileName);
|
||||||
|
LoadedWriteTime = File.GetLastWriteTime(FileName);
|
||||||
|
|
||||||
|
current = jsource.To<T>();
|
||||||
|
}
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
current = value;
|
||||||
|
Save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Save(){
|
||||||
|
JSONConverter.From(current).WriteTo(FileName,true);
|
||||||
|
LoadedWriteTime = File.GetLastWriteTime(FileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
232
JSON.cs
232
JSON.cs
|
@ -6,6 +6,8 @@ using System.Net;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
|
using System.CodeDom;
|
||||||
|
using System.Globalization;
|
||||||
|
|
||||||
namespace sharp.json
|
namespace sharp.json
|
||||||
{
|
{
|
||||||
|
@ -17,6 +19,7 @@ namespace sharp.json
|
||||||
public virtual long Integer { get { throw new NotImplementedException(); } }
|
public virtual long Integer { get { throw new NotImplementedException(); } }
|
||||||
public virtual string String { get { throw new NotImplementedException(); } }
|
public virtual string String { get { throw new NotImplementedException(); } }
|
||||||
public virtual bool Boolean { get { throw new NotImplementedException(); } }
|
public virtual bool Boolean { get { throw new NotImplementedException(); } }
|
||||||
|
public virtual object Object { get { throw new NotImplementedException(); } }
|
||||||
|
|
||||||
public virtual JSON this[int n]
|
public virtual JSON this[int n]
|
||||||
{
|
{
|
||||||
|
@ -78,142 +81,108 @@ namespace sharp.json
|
||||||
return b ? JSONSpecial.True : JSONSpecial.False;
|
return b ? JSONSpecial.True : JSONSpecial.False;
|
||||||
}
|
}
|
||||||
|
|
||||||
public T To<T>(){
|
public static implicit operator string(JSON json)
|
||||||
object o = Create(typeof(T));
|
{
|
||||||
return (T)o;
|
return json.String;
|
||||||
|
}
|
||||||
|
public static implicit operator bool(JSON json)
|
||||||
|
{
|
||||||
|
return json.Boolean;
|
||||||
|
}
|
||||||
|
public static implicit operator int(JSON json)
|
||||||
|
{
|
||||||
|
return (int)json.Integer;
|
||||||
|
}
|
||||||
|
public static implicit operator long(JSON json)
|
||||||
|
{
|
||||||
|
return json.Integer;
|
||||||
|
}
|
||||||
|
public static implicit operator double(JSON json)
|
||||||
|
{
|
||||||
|
return json.Double;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WriteTo(Stream stream){
|
public T To<T>()
|
||||||
byte[] data = Encoding.ASCII.GetBytes(ToString());
|
{
|
||||||
|
return JSONConverter.To<T>(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JSON From(object o){
|
||||||
|
return JSONConverter.From(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void WriteTo(Stream stream)
|
||||||
|
{
|
||||||
|
WriteTo(stream);
|
||||||
|
}
|
||||||
|
public void WriteTo(Stream stream,bool pretty){
|
||||||
|
byte[] data = Encoding.ASCII.GetBytes(pretty ? prettyFormat() : ToString() );
|
||||||
stream.Write(data,0,data.Length);
|
stream.Write(data,0,data.Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WriteTo(String filename)
|
public void WriteTo(String filename)
|
||||||
|
{
|
||||||
|
WriteTo(filename, false);
|
||||||
|
}
|
||||||
|
public void WriteTo(String filename,bool pretty)
|
||||||
{
|
{
|
||||||
FileStream fs = new FileStream(filename, FileMode.Create);
|
FileStream fs = new FileStream(filename, FileMode.Create);
|
||||||
WriteTo(fs);
|
WriteTo(fs,pretty);
|
||||||
fs.Close();
|
fs.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static JSON ReadFrom(string filename){
|
public static JSON ReadFrom(string filename)
|
||||||
|
{
|
||||||
|
return ReadFrom(filename, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JSON ReadFrom(string filename, object defaultValue)
|
||||||
|
{
|
||||||
JSONParser parser = new JSONParser();
|
JSONParser parser = new JSONParser();
|
||||||
string source = File.ReadAllText(filename);
|
string source = "";
|
||||||
|
try
|
||||||
|
{
|
||||||
|
source = File.ReadAllText(filename);
|
||||||
|
}
|
||||||
|
catch (FileNotFoundException e)
|
||||||
|
{
|
||||||
|
return JSON.From(defaultValue);
|
||||||
|
}
|
||||||
return parser.Parse(source);
|
return parser.Parse(source);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private object Create(Type t)
|
public static JSON ReadFrom(string filename,JSON defaultValue){
|
||||||
{
|
JSONParser parser = new JSONParser();
|
||||||
if (t.IsPrimitive || (t == typeof(string)) )
|
string source = "";
|
||||||
|
try
|
||||||
{
|
{
|
||||||
return CreatePrimitive(t);
|
source = File.ReadAllText(filename);
|
||||||
|
} catch (FileNotFoundException e){
|
||||||
|
return defaultValue;
|
||||||
}
|
}
|
||||||
|
return parser.Parse(source);
|
||||||
if (this.JSONType == JSONTypes.Object)
|
|
||||||
{
|
|
||||||
return CreateObject(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((this.JSONType == JSONTypes.Array) && (t.IsArray))
|
|
||||||
{
|
|
||||||
return CreateArray(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new InvalidCastException(String.Format("JSON {0} can't be casted to {1}", this.JSONType.ToString(), t.Name));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private object CreatePrimitive(Type t){
|
public object Native(){
|
||||||
|
switch (JSONType)
|
||||||
if ((this.JSONType == JSONTypes.Null)){
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((this.JSONType == JSONTypes.Array) || (this.JSONType == JSONTypes.Object)){
|
|
||||||
throw new InvalidCastException(String.Format("JSON {0} can't be casted to {1}",this.JSONType.ToString(),t.Name));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (t.Equals(typeof(int)) || t.Equals(typeof(long)) || t.Equals(typeof(short))){
|
|
||||||
return (object)this.Integer;
|
|
||||||
}
|
|
||||||
if (t.Equals(typeof(double)) || t.Equals(typeof(float)))
|
|
||||||
{
|
{
|
||||||
return (object)this.Double;
|
case JSONTypes.Null:
|
||||||
|
return null;
|
||||||
|
case JSONTypes.True:
|
||||||
|
return true;
|
||||||
|
case JSONTypes.False:
|
||||||
|
return false;
|
||||||
|
case JSONTypes.Number:
|
||||||
|
return Double;
|
||||||
|
case JSONTypes.String:
|
||||||
|
return String;
|
||||||
}
|
}
|
||||||
if (t.Equals(typeof(string)))
|
throw new InvalidCastException(String.Format("Can't create native type of {0}",this.JSONType));
|
||||||
{
|
|
||||||
return (object)this.String;
|
|
||||||
}
|
|
||||||
if (t.Equals(typeof(Boolean)))
|
|
||||||
{
|
|
||||||
return (object)this.Boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Exception(String.Format("Unsupported primitive type",t.Name));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private object CreateObject(Type t){
|
|
||||||
if (t.GetConstructor(new Type[] { typeof(JSON) } ) != null){
|
|
||||||
return Activator.CreateInstance(t, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
object instance = Activator.CreateInstance(t);
|
|
||||||
Dictionary<string, FieldPropertyInfo> assignedFields = new Dictionary<string, FieldPropertyInfo>();
|
|
||||||
|
|
||||||
foreach (FieldInfo fi in t.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
|
|
||||||
{
|
|
||||||
foreach (JSONField f in fi.GetCustomAttributes<JSONField>())
|
|
||||||
{
|
|
||||||
if (this.Contains(f.Alias))
|
|
||||||
{
|
|
||||||
if (!assignedFields.ContainsKey(f.Alias) || assignedFields[f.Alias].IsAutoAssigned){
|
|
||||||
assignedFields[f.Alias] = new FieldPropertyInfo(fi, false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!assignedFields.ContainsKey(fi.Name) && this.Contains(fi.Name)){
|
|
||||||
assignedFields[fi.Name] = new FieldPropertyInfo(fi, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (PropertyInfo pi in t.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
|
|
||||||
{
|
|
||||||
foreach (JSONField f in pi.GetCustomAttributes<JSONField>())
|
|
||||||
{
|
|
||||||
if (this.Contains(f.Alias))
|
|
||||||
{
|
|
||||||
if (!assignedFields.ContainsKey(f.Alias) || assignedFields[f.Alias].IsAutoAssigned)
|
|
||||||
{
|
|
||||||
assignedFields[f.Alias] = new FieldPropertyInfo(pi, false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!assignedFields.ContainsKey(pi.Name) && this.Contains(pi.Name))
|
|
||||||
{
|
|
||||||
assignedFields[pi.Name] = new FieldPropertyInfo(pi, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (KeyValuePair<string,FieldPropertyInfo> e in assignedFields){
|
|
||||||
e.Value.setValue(instance, this[e.Key].Create(e.Value.ValueType));
|
|
||||||
}
|
|
||||||
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
private object CreateArray(Type t)
|
|
||||||
{
|
|
||||||
Array a = Array.CreateInstance(t.GetElementType(), this.Count);
|
|
||||||
|
|
||||||
for (int n = 0; n < this.Count;n++){
|
|
||||||
a.SetValue(this[n].Create(t.GetElementType()),n);
|
|
||||||
}
|
|
||||||
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual IEnumerator<JSON> GetEnumerator()
|
public virtual IEnumerator<JSON> GetEnumerator()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
|
@ -223,46 +192,5 @@ namespace sharp.json
|
||||||
{
|
{
|
||||||
return (IEnumerator)GetEnumerator();
|
return (IEnumerator)GetEnumerator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct FieldPropertyInfo {
|
|
||||||
public bool IsAutoAssigned { get; set; }
|
|
||||||
FieldInfo FieldInfo { get; set; }
|
|
||||||
PropertyInfo PropertyInfo { get; set; }
|
|
||||||
|
|
||||||
public FieldPropertyInfo(PropertyInfo propertyInfo,bool autoAssigned)
|
|
||||||
{
|
|
||||||
this.IsAutoAssigned = autoAssigned;
|
|
||||||
this.PropertyInfo = propertyInfo;
|
|
||||||
this.FieldInfo = null;
|
|
||||||
}
|
|
||||||
public FieldPropertyInfo(FieldInfo fieldInfo,bool autoAssigned)
|
|
||||||
{
|
|
||||||
this.IsAutoAssigned = autoAssigned;
|
|
||||||
this.PropertyInfo = null;
|
|
||||||
this.FieldInfo = fieldInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setValue(object inst,object value){
|
|
||||||
if (PropertyInfo != null){
|
|
||||||
PropertyInfo.SetValue(inst,value);
|
|
||||||
} else if (FieldInfo != null){
|
|
||||||
FieldInfo.SetValue(inst,value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Type ValueType {
|
|
||||||
get {
|
|
||||||
if (PropertyInfo != null){
|
|
||||||
return PropertyInfo.PropertyType;
|
|
||||||
} else if (FieldInfo != null){
|
|
||||||
return FieldInfo.FieldType;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
10
JSONArray.cs
10
JSONArray.cs
|
@ -9,6 +9,16 @@ namespace sharp.json
|
||||||
public JSONArray()
|
public JSONArray()
|
||||||
: base(JSONTypes.Array) { }
|
: base(JSONTypes.Array) { }
|
||||||
|
|
||||||
|
public JSONArray(object[] init)
|
||||||
|
: base(JSONTypes.Array)
|
||||||
|
{
|
||||||
|
foreach (object o in init)
|
||||||
|
{
|
||||||
|
this.values.Add(JSONConverter.From(o));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
List<JSON> values = new List<JSON>();
|
List<JSON> values = new List<JSON>();
|
||||||
|
|
||||||
public override bool Boolean
|
public override bool Boolean
|
||||||
|
|
|
@ -0,0 +1,350 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using sharp.json.attributes;
|
||||||
|
using System.Reflection;
|
||||||
|
using sharp.extensions;
|
||||||
|
namespace sharp.json
|
||||||
|
{
|
||||||
|
public static class JSONConverter
|
||||||
|
{
|
||||||
|
delegate object ConvertToDelegate(Type t,JSON json);
|
||||||
|
|
||||||
|
static Dictionary<Type, ConvertToDelegate> toDelegates = new Dictionary<Type, ConvertToDelegate>{
|
||||||
|
{ typeof(string), (t, json) => json.String },
|
||||||
|
{ typeof(int), (t, json) => json.Integer },
|
||||||
|
{ typeof(short), (t, json) => json.Integer },
|
||||||
|
{ typeof(long), (t, json) => json.Integer },
|
||||||
|
{ typeof(uint), (t, json) => json.Integer },
|
||||||
|
{ typeof(ushort), (t, json) => json.Integer },
|
||||||
|
{ typeof(ulong), (t, json) => json.Integer },
|
||||||
|
{ typeof(double), (t, json) => json.Double },
|
||||||
|
{ typeof(float), (t, json) => json.Double },
|
||||||
|
{ typeof(bool), (t, json) => json.Boolean },
|
||||||
|
{ typeof(DateTime), (t, json) => DateTime.Parse(json.String, CultureInfo.InvariantCulture) },
|
||||||
|
{ typeof(Guid), (t, json) => Guid.Parse(json.String)},
|
||||||
|
{ typeof(object), ToObject }
|
||||||
|
};
|
||||||
|
|
||||||
|
public static T To<T>(JSON json)
|
||||||
|
{
|
||||||
|
Type t = typeof(T);
|
||||||
|
return (T)(object)To(t, json);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JSON From(object value)
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
return JSONSpecial.Null;
|
||||||
|
}
|
||||||
|
return From(value.GetType(), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static object To(Type t,JSON json){
|
||||||
|
|
||||||
|
if (json.JSONType == JSONTypes.Null){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t.IsEnum){
|
||||||
|
return Enum.Parse(t, json.String);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toDelegates.ContainsKey(t))
|
||||||
|
{
|
||||||
|
return toDelegates[t](t, json);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t.IsArray){
|
||||||
|
return ToArray(t, json);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!t.IsPrimitive){
|
||||||
|
return ToObject(t, json);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
throw new InvalidCastException(String.Format("JSON {0} can't be casted to {1}", json.JSONType.ToString(), t.Name));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ApplyObject(JSON json, object o)
|
||||||
|
{
|
||||||
|
FieldPropertyInfo[] fpilist = fpi(o.GetType());
|
||||||
|
foreach (FieldPropertyInfo fpi in fpilist)
|
||||||
|
{
|
||||||
|
if (json.Contains(fpi.Key))
|
||||||
|
{
|
||||||
|
fpi.setValue(o, To(fpi.ValueType, json[fpi.Key]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static object ToObject(Type t,JSON json){
|
||||||
|
ConstructorInfo ci = t.GetConstructor(new Type[] { typeof(JSON) });
|
||||||
|
if (ci != null)
|
||||||
|
{
|
||||||
|
if (ci.GetParameters()[0].ParameterType.Equals(typeof(JSON)))
|
||||||
|
{
|
||||||
|
return Activator.CreateInstance(t, (object)json);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONClassPolicy cp = t.GetCustomAttribute<JSONClassPolicy>();
|
||||||
|
if (cp == null)
|
||||||
|
{
|
||||||
|
cp = new JSONClassPolicy();
|
||||||
|
}
|
||||||
|
return ToObject(t, json, cp.Policy);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static object ToObject(Type t, JSON json,JSONPolicy policy)
|
||||||
|
{
|
||||||
|
object oi = Activator.CreateInstance(t);
|
||||||
|
|
||||||
|
ApplyObject(json,oi);
|
||||||
|
|
||||||
|
return oi;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static object ToArray(Type t,JSON json)
|
||||||
|
{
|
||||||
|
Array a = Array.CreateInstance(t.GetElementType(), json.Count);
|
||||||
|
|
||||||
|
for (int n = 0; n < json.Count; n++)
|
||||||
|
{
|
||||||
|
a.SetValue(To(t.GetElementType(),json[n]), n);
|
||||||
|
}
|
||||||
|
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JSON From(Type t, object value)
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
return JSONSpecial.Null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t == null)
|
||||||
|
{
|
||||||
|
t = value.GetType();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((t.IsPrimitive) || (t == typeof(string)))
|
||||||
|
{
|
||||||
|
return FromPrimitive(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t == typeof(DateTime))
|
||||||
|
{
|
||||||
|
return new JSONString(((DateTime)value).ToString(CultureInfo.InvariantCulture));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t == typeof(Guid))
|
||||||
|
{
|
||||||
|
return ((Guid)value).ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t.IsEnum)
|
||||||
|
{
|
||||||
|
return new JSONString(value.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t.IsArray)
|
||||||
|
{
|
||||||
|
JSONArray ja = new JSONArray();
|
||||||
|
|
||||||
|
Array a = (Array)value;
|
||||||
|
|
||||||
|
Type et = t.GetElementType();
|
||||||
|
if (et == typeof(object))
|
||||||
|
{
|
||||||
|
et = null;
|
||||||
|
}
|
||||||
|
foreach (object e in a)
|
||||||
|
{
|
||||||
|
ja.Add(From(et, e));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ja;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FromObject(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JSON FromPrimitive(object value)
|
||||||
|
{
|
||||||
|
Type t = value.GetType();
|
||||||
|
|
||||||
|
if (typeof(int).Equals(t))
|
||||||
|
{
|
||||||
|
return new JSONNumber((int)value);
|
||||||
|
}
|
||||||
|
if (typeof(long).Equals(t))
|
||||||
|
{
|
||||||
|
return new JSONNumber((long)value);
|
||||||
|
}
|
||||||
|
if (typeof(double).Equals(t))
|
||||||
|
{
|
||||||
|
return new JSONNumber((double)value);
|
||||||
|
}
|
||||||
|
if (typeof(float).Equals(t))
|
||||||
|
{
|
||||||
|
return new JSONNumber((float)value);
|
||||||
|
}
|
||||||
|
if (typeof(string).Equals(t))
|
||||||
|
{
|
||||||
|
return new JSONString(value.ToString());
|
||||||
|
}
|
||||||
|
if (typeof(bool).Equals(t))
|
||||||
|
{
|
||||||
|
return ((bool)value) ? JSONSpecial.True : JSONSpecial.False;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new NotImplementedException(String.Format("Cast of {0} to JSON is not (yet) supported", t.Name));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JSON FromObject(object value)
|
||||||
|
{
|
||||||
|
return FromObject(value.GetType(), value);
|
||||||
|
}
|
||||||
|
public static JSON FromObject(Type type, object value)
|
||||||
|
{
|
||||||
|
Type t = value.GetType();
|
||||||
|
JSONObject jo = new JSONObject();
|
||||||
|
|
||||||
|
foreach (FieldPropertyInfo fpi in fpi(t)){
|
||||||
|
jo[fpi.Key] = JSON.From(fpi.getValue(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
return jo;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static FieldPropertyInfo[] fpi(Type t)
|
||||||
|
{
|
||||||
|
JSONClassPolicy cp = t.GetCustomAttribute<JSONClassPolicy>();
|
||||||
|
if (cp == null)
|
||||||
|
{
|
||||||
|
cp = new JSONClassPolicy();
|
||||||
|
}
|
||||||
|
return fpi(t, cp);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static FieldPropertyInfo[] fpi(Type t,JSONClassPolicy cp)
|
||||||
|
{
|
||||||
|
BindingFlags bf;
|
||||||
|
switch (cp.Policy){
|
||||||
|
case JSONPolicy.ALL:
|
||||||
|
bf = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly;
|
||||||
|
break;
|
||||||
|
case JSONPolicy.ATTRIBUTED:
|
||||||
|
bf = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly;
|
||||||
|
break;
|
||||||
|
case JSONPolicy.NONPUBLIC:
|
||||||
|
bf = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
bf = BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
List<FieldPropertyInfo> fpilist = new List<FieldPropertyInfo>();
|
||||||
|
|
||||||
|
foreach (FieldInfo fi in t.GetFields(bf))
|
||||||
|
{
|
||||||
|
fpilist.Add(new FieldPropertyInfo(fi));
|
||||||
|
}
|
||||||
|
foreach (PropertyInfo pi in t.GetProperties(bf))
|
||||||
|
{
|
||||||
|
fpilist.Add(new FieldPropertyInfo(pi));
|
||||||
|
}
|
||||||
|
|
||||||
|
FieldPropertyInfo[] temp = fpilist.ToArray();
|
||||||
|
fpilist.Clear();
|
||||||
|
|
||||||
|
foreach (FieldPropertyInfo fpi in temp){
|
||||||
|
if ((cp.Policy != JSONPolicy.ATTRIBUTED) || (fpi.JSONField != null))
|
||||||
|
{
|
||||||
|
fpilist.Add(fpi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!t.BaseType.IsNull()){
|
||||||
|
fpilist.AddRange(fpi(t.BaseType,cp));
|
||||||
|
}
|
||||||
|
|
||||||
|
return fpilist.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct FieldPropertyInfo
|
||||||
|
{
|
||||||
|
public String Key { get; set; }
|
||||||
|
|
||||||
|
FieldInfo FieldInfo { get; set; }
|
||||||
|
PropertyInfo PropertyInfo { get; set; }
|
||||||
|
|
||||||
|
public JSONField JSONField { get; set; }
|
||||||
|
|
||||||
|
public FieldPropertyInfo(PropertyInfo propertyInfo)
|
||||||
|
{
|
||||||
|
this.PropertyInfo = propertyInfo;
|
||||||
|
this.FieldInfo = null;
|
||||||
|
this.JSONField = propertyInfo.GetCustomAttribute<JSONField>();
|
||||||
|
this.Key = (this.JSONField == null) ? propertyInfo.Name : ((this.JSONField.Alias == null) ? propertyInfo.Name : this.JSONField.Alias);
|
||||||
|
}
|
||||||
|
public FieldPropertyInfo(FieldInfo fieldInfo)
|
||||||
|
{
|
||||||
|
this.PropertyInfo = null;
|
||||||
|
this.FieldInfo = fieldInfo;
|
||||||
|
this.JSONField = fieldInfo.GetCustomAttribute<JSONField>();
|
||||||
|
this.Key = (this.JSONField == null) ? fieldInfo.Name : ((this.JSONField.Alias == null) ? fieldInfo.Name : this.JSONField.Alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(object inst, object value)
|
||||||
|
{
|
||||||
|
if (PropertyInfo != null)
|
||||||
|
{
|
||||||
|
PropertyInfo.SetValue(inst, value);
|
||||||
|
}
|
||||||
|
else if (FieldInfo != null)
|
||||||
|
{
|
||||||
|
FieldInfo.SetValue(inst, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public object getValue(object inst)
|
||||||
|
{
|
||||||
|
if ((PropertyInfo != null)&&(!PropertyInfo.GetMethod.IsNull()))
|
||||||
|
{
|
||||||
|
return PropertyInfo.GetValue(inst);
|
||||||
|
}
|
||||||
|
else if (FieldInfo != null)
|
||||||
|
{
|
||||||
|
return FieldInfo.GetValue(inst);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type ValueType
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (PropertyInfo != null)
|
||||||
|
{
|
||||||
|
return PropertyInfo.PropertyType;
|
||||||
|
}
|
||||||
|
else if (FieldInfo != null)
|
||||||
|
{
|
||||||
|
return FieldInfo.FieldType;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -71,7 +71,7 @@ namespace sharp.json
|
||||||
|
|
||||||
for (int n=0;n<keys.Length;n++)
|
for (int n=0;n<keys.Length;n++)
|
||||||
{
|
{
|
||||||
sb.Append(new JSONString(keys[n]));
|
sb.Append(new JSONString(keys[n]).ToString());
|
||||||
sb.Append(":");
|
sb.Append(":");
|
||||||
sb.Append(this[keys[n]].ToString());
|
sb.Append(this[keys[n]].ToString());
|
||||||
if (n+1 < keys.Length){
|
if (n+1 < keys.Length){
|
||||||
|
|
|
@ -281,6 +281,7 @@ namespace sharp.json
|
||||||
LexerPathSegment digit_c = new LexerPathSegment(CharGroup.digit,true);
|
LexerPathSegment digit_c = new LexerPathSegment(CharGroup.digit,true);
|
||||||
LexerPathSegment dot = new LexerPathSegment('.');
|
LexerPathSegment dot = new LexerPathSegment('.');
|
||||||
LexerPathSegment ee = new LexerPathSegment(eE);
|
LexerPathSegment ee = new LexerPathSegment(eE);
|
||||||
|
LexerPathSegment eminus = new LexerPathSegment(CharGroup.minus);
|
||||||
LexerPathSegment plusminus = new LexerPathSegment(CharGroup.plusminus);
|
LexerPathSegment plusminus = new LexerPathSegment(CharGroup.plusminus);
|
||||||
|
|
||||||
head.AddFollower(minus);
|
head.AddFollower(minus);
|
||||||
|
@ -309,6 +310,8 @@ namespace sharp.json
|
||||||
ee.AddFollower(digit_c);
|
ee.AddFollower(digit_c);
|
||||||
ee.AddFollower(plusminus);
|
ee.AddFollower(plusminus);
|
||||||
|
|
||||||
|
plusminus.AddFollower(digit_c);
|
||||||
|
|
||||||
digit_c.AddFollower(digit_c);
|
digit_c.AddFollower(digit_c);
|
||||||
|
|
||||||
return head;
|
return head;
|
||||||
|
|
|
@ -37,7 +37,17 @@ namespace sharp.json
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpResponse response = req.Send();
|
HttpResponse response = req.Send();
|
||||||
return jsonParser.Parse(response.ContentText);
|
|
||||||
|
try {
|
||||||
|
return jsonParser.Parse(response.ContentText);
|
||||||
|
} catch (Exception e){
|
||||||
|
Console.WriteLine("JSONWebRequest could not parse response.");
|
||||||
|
Console.WriteLine("Response was:");
|
||||||
|
Console.WriteLine(">-------------------------------------------");
|
||||||
|
Console.WriteLine(response.ContentText);
|
||||||
|
Console.WriteLine("<-------------------------------------------");
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
using System;
|
||||||
|
namespace sharp.json.attributes
|
||||||
|
{
|
||||||
|
public enum JSONPolicy { ALL, PUBLIC, NONPUBLIC, ATTRIBUTED }
|
||||||
|
|
||||||
|
public class JSONClassPolicy : Attribute
|
||||||
|
{
|
||||||
|
public JSONPolicy Policy { get; set; } = JSONPolicy.PUBLIC;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace sharp.json
|
namespace sharp.json.attributes
|
||||||
{
|
{
|
||||||
public class JSONField : Attribute
|
public class JSONField : Attribute
|
||||||
{
|
{
|
|
@ -17,21 +17,25 @@ namespace json.test
|
||||||
|
|
||||||
public static void Main(string[] args)
|
public static void Main(string[] args)
|
||||||
{
|
{
|
||||||
|
|
||||||
JSON json;
|
JSON json;
|
||||||
JSONParser jsonparser = new JSONParser();
|
JSONParser jsonparser = new JSONParser();
|
||||||
|
|
||||||
Console.WriteLine("JSON test Patterns:");
|
json = jsonparser.Parse("4.9125E-05");
|
||||||
Console.WriteLine();
|
Console.WriteLine(json.ToString());
|
||||||
|
|
||||||
foreach (string src in sources){
|
//Console.WriteLine("JSON test Patterns:");
|
||||||
json = jsonparser.Parse(src);
|
//Console.WriteLine();
|
||||||
Console.WriteLine("NEW PARSER: {0}",json.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
json = jsonparser.Parse(File.ReadAllText("test.json"));
|
//foreach (string src in sources){
|
||||||
Console.WriteLine("");
|
// json = jsonparser.Parse(src);
|
||||||
Console.WriteLine("test.json file:");
|
// Console.WriteLine("NEW PARSER: {0}",json.ToString());
|
||||||
Console.WriteLine("PARSED: {0}",json.ToString());
|
//}
|
||||||
|
|
||||||
|
//json = jsonparser.Parse(File.ReadAllText("test.json"));
|
||||||
|
//Console.WriteLine("");
|
||||||
|
//Console.WriteLine("test.json file:");
|
||||||
|
//Console.WriteLine("PARSED: {0}",json.ToString());
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
using System;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Net;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace sharp.json.network
|
||||||
|
{
|
||||||
|
public class JSONTcpClient
|
||||||
|
{
|
||||||
|
TcpClient client;
|
||||||
|
StreamReader reader;
|
||||||
|
StreamWriter writer;
|
||||||
|
|
||||||
|
JSONParser parser = new JSONParser();
|
||||||
|
|
||||||
|
public JSONTcpClient(int port)
|
||||||
|
{
|
||||||
|
this.client = new TcpClient();
|
||||||
|
this.client.Connect("127.0.0.1",port);
|
||||||
|
this.initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
public JSONTcpClient(TcpClient client)
|
||||||
|
{
|
||||||
|
this.client = client;
|
||||||
|
initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initialize(){
|
||||||
|
this.reader = new StreamReader(client.GetStream());
|
||||||
|
this.writer = new StreamWriter(client.GetStream());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public JSON Receive()
|
||||||
|
{
|
||||||
|
string line = reader.ReadLine();
|
||||||
|
JSON json = parser.Parse(line);
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Send(JSON json){
|
||||||
|
writer.WriteLine(json.ToString());
|
||||||
|
writer.Flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close(){
|
||||||
|
this.client.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
using System;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Net;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace sharp.json.network
|
||||||
|
{
|
||||||
|
public delegate void JSONClientConnected(JSONTcpClient jsonClient);
|
||||||
|
|
||||||
|
public class JSONTcpServer
|
||||||
|
{
|
||||||
|
public JSONClientConnected ClientConnected { get; set; }
|
||||||
|
|
||||||
|
TcpListener listener;
|
||||||
|
Thread serverThread;
|
||||||
|
bool shouldExit;
|
||||||
|
|
||||||
|
public JSONTcpServer(int port)
|
||||||
|
{
|
||||||
|
this.listener = new TcpListener(IPAddress.Loopback, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Start()
|
||||||
|
{
|
||||||
|
lock (this){
|
||||||
|
if (serverThread == null){
|
||||||
|
serverThread = new Thread(Serve);
|
||||||
|
serverThread.Start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void Stop()
|
||||||
|
{
|
||||||
|
lock (this){
|
||||||
|
shouldExit = true;
|
||||||
|
this.listener.Stop();
|
||||||
|
Monitor.Wait(this);
|
||||||
|
this.serverThread = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Serve()
|
||||||
|
{
|
||||||
|
this.listener.Start();
|
||||||
|
|
||||||
|
while (true){
|
||||||
|
lock (this){
|
||||||
|
if (shouldExit){
|
||||||
|
shouldExit = false;
|
||||||
|
Monitor.Pulse(this);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
TcpClient client = this.listener.AcceptTcpClient();
|
||||||
|
ThreadPool.QueueUserWorkItem((state) => fireClientConnected(client));
|
||||||
|
} catch (SocketException se){
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fireClientConnected(TcpClient client){
|
||||||
|
if (ClientConnected != null){
|
||||||
|
JSONTcpClient jsonCLient = new JSONTcpClient(client);
|
||||||
|
ClientConnected.Invoke(jsonCLient);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -42,7 +42,12 @@
|
||||||
<Compile Include="JSONWebRequest.cs" />
|
<Compile Include="JSONWebRequest.cs" />
|
||||||
<Compile Include="JSONSerializer.cs" />
|
<Compile Include="JSONSerializer.cs" />
|
||||||
<Compile Include="JSONParser.cs" />
|
<Compile Include="JSONParser.cs" />
|
||||||
<Compile Include="JSONField.cs" />
|
<Compile Include="FileBackedJSONValue.cs" />
|
||||||
|
<Compile Include="network\JSONTcpServer.cs" />
|
||||||
|
<Compile Include="network\JSONTcpClient.cs" />
|
||||||
|
<Compile Include="attributes\JSONClassPolicy.cs" />
|
||||||
|
<Compile Include="attributes\JSONField.cs" />
|
||||||
|
<Compile Include="JSONConverter.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\sharp-extensions\sharp.extensions.csproj">
|
<ProjectReference Include="..\sharp-extensions\sharp.extensions.csproj">
|
||||||
|
@ -62,6 +67,10 @@
|
||||||
<Name>sharp.contracts</Name>
|
<Name>sharp.contracts</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="network\" />
|
||||||
|
<Folder Include="attributes\" />
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||||
<ProjectExtensions>
|
<ProjectExtensions>
|
||||||
<MonoDevelop>
|
<MonoDevelop>
|
||||||
|
|
Loading…
Reference in New Issue