2017-10-26 16:41:14 +02:00
|
|
|
|
using System;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Collections.Generic;
|
2017-11-03 13:13:09 +01:00
|
|
|
|
using System.Net;
|
|
|
|
|
using System.Reflection;
|
|
|
|
|
using System.Collections;
|
|
|
|
|
using System.Security.Cryptography;
|
2017-10-26 16:41:14 +02:00
|
|
|
|
|
|
|
|
|
namespace sharp.json
|
|
|
|
|
{
|
2017-11-03 13:13:09 +01:00
|
|
|
|
public delegate object JSONActivationDelegate(Type t);
|
|
|
|
|
|
|
|
|
|
public abstract class JSON : IEnumerable<JSON>
|
2017-10-26 16:41:14 +02:00
|
|
|
|
{
|
2017-11-03 13:13:09 +01:00
|
|
|
|
public virtual double Double { get { throw new NotImplementedException(); } }
|
|
|
|
|
public virtual long Integer { get { throw new NotImplementedException(); } }
|
|
|
|
|
public virtual string String { get { throw new NotImplementedException(); } }
|
|
|
|
|
public virtual bool Boolean { get { throw new NotImplementedException(); } }
|
|
|
|
|
|
|
|
|
|
public virtual JSON this[int n]
|
|
|
|
|
{
|
|
|
|
|
get { throw new NotImplementedException(String.Format("{0} has no numbered elements",GetType().Name)); }
|
|
|
|
|
set { throw new NotImplementedException(String.Format("{0} has no numbered elements",GetType().Name)); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public virtual JSON this[string name] {
|
|
|
|
|
get { throw new NotImplementedException(String.Format("{0} has no named elements", GetType().Name)); }
|
|
|
|
|
set { throw new NotImplementedException(String.Format("{0} has no named elements", GetType().Name)); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public virtual int Count { get { return 0; } }
|
|
|
|
|
|
|
|
|
|
public virtual bool Contains(object o){
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public virtual void Add(JSON child)
|
|
|
|
|
{
|
|
|
|
|
throw new NotImplementedException(String.Format("{0} has no numbered elements", GetType().Name));
|
|
|
|
|
}
|
|
|
|
|
public virtual void Remove(JSON child)
|
|
|
|
|
{
|
|
|
|
|
throw new NotImplementedException(String.Format("{0} has no numbered elements", GetType().Name));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public JSONTypes JSONType { get; private set; }
|
|
|
|
|
|
|
|
|
|
protected JSON(JSONTypes type){
|
|
|
|
|
JSONType = type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public abstract string[] prettyPrint();
|
|
|
|
|
public override abstract string ToString();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public string prettyFormat(){
|
|
|
|
|
return String.Join("\n", prettyPrint());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static implicit operator JSON(Double src)
|
|
|
|
|
{
|
|
|
|
|
return new JSONNumber(src);
|
|
|
|
|
}
|
|
|
|
|
public static implicit operator JSON(int src)
|
|
|
|
|
{
|
|
|
|
|
return new JSONNumber(src);
|
|
|
|
|
}
|
|
|
|
|
public static implicit operator JSON(string text)
|
|
|
|
|
{
|
|
|
|
|
return new JSONString(text);
|
|
|
|
|
}
|
|
|
|
|
public static implicit operator JSON(bool b)
|
|
|
|
|
{
|
|
|
|
|
return b ? JSONSpecial.True : JSONSpecial.False;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public T To<T>(){
|
|
|
|
|
object o = Create(typeof(T));
|
|
|
|
|
return (T)o;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void WriteTo(Stream stream){
|
|
|
|
|
byte[] data = Encoding.ASCII.GetBytes(ToString());
|
|
|
|
|
stream.Write(data,0,data.Length);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void WriteTo(String filename)
|
|
|
|
|
{
|
|
|
|
|
FileStream fs = new FileStream(filename, FileMode.Create);
|
|
|
|
|
WriteTo(fs);
|
|
|
|
|
fs.Close();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static JSON ReadFrom(string filename){
|
|
|
|
|
JSONParser parser = new JSONParser();
|
|
|
|
|
string source = File.ReadAllText(filename);
|
|
|
|
|
return parser.Parse(source);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private object Create(Type t)
|
|
|
|
|
{
|
|
|
|
|
if (t.IsPrimitive || (t == typeof(string)) )
|
|
|
|
|
{
|
|
|
|
|
return CreatePrimitive(t);
|
|
|
|
|
}
|
2017-10-26 16:41:14 +02:00
|
|
|
|
|
2017-11-03 13:13:09 +01:00
|
|
|
|
if (this.JSONType == JSONTypes.Object)
|
|
|
|
|
{
|
|
|
|
|
return CreateObject(t);
|
2017-10-26 16:41:14 +02:00
|
|
|
|
}
|
2017-11-03 13:13:09 +01:00
|
|
|
|
|
|
|
|
|
if ((this.JSONType == JSONTypes.Array) && (t.IsArray))
|
|
|
|
|
{
|
|
|
|
|
return CreateArray(t);
|
2017-10-26 16:41:14 +02:00
|
|
|
|
}
|
2017-11-03 13:13:09 +01:00
|
|
|
|
|
|
|
|
|
throw new InvalidCastException(String.Format("JSON {0} can't be casted to {1}", this.JSONType.ToString(), t.Name));
|
2017-10-26 16:41:14 +02:00
|
|
|
|
}
|
|
|
|
|
|
2017-11-03 13:13:09 +01:00
|
|
|
|
private object CreatePrimitive(Type t){
|
|
|
|
|
|
|
|
|
|
if ((this.JSONType == JSONTypes.Null)){
|
|
|
|
|
return null;
|
2017-10-26 16:41:14 +02:00
|
|
|
|
}
|
2017-11-03 13:13:09 +01:00
|
|
|
|
|
|
|
|
|
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));
|
2017-10-26 16:41:14 +02:00
|
|
|
|
}
|
2017-11-03 13:13:09 +01:00
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
if (t.Equals(typeof(string)))
|
|
|
|
|
{
|
|
|
|
|
return (object)this.String;
|
|
|
|
|
}
|
|
|
|
|
if (t.Equals(typeof(Boolean)))
|
|
|
|
|
{
|
|
|
|
|
return (object)this.Boolean;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
throw new Exception(String.Format("Unsupported primitive type",t.Name));
|
2017-10-26 16:41:14 +02:00
|
|
|
|
}
|
|
|
|
|
|
2017-11-03 13:13:09 +01:00
|
|
|
|
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;
|
2017-10-26 16:41:14 +02:00
|
|
|
|
}
|
2017-11-03 13:13:09 +01:00
|
|
|
|
|
|
|
|
|
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;
|
2017-10-26 16:41:14 +02:00
|
|
|
|
}
|
|
|
|
|
|
2017-11-03 13:13:09 +01:00
|
|
|
|
public virtual IEnumerator<JSON> GetEnumerator()
|
|
|
|
|
{
|
|
|
|
|
throw new NotImplementedException();
|
2017-10-26 16:41:14 +02:00
|
|
|
|
}
|
|
|
|
|
|
2017-11-03 13:13:09 +01:00
|
|
|
|
IEnumerator IEnumerable.GetEnumerator()
|
|
|
|
|
{
|
|
|
|
|
return (IEnumerator)GetEnumerator();
|
2017-10-26 16:41:14 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2017-11-03 13:13:09 +01:00
|
|
|
|
struct FieldPropertyInfo {
|
|
|
|
|
public bool IsAutoAssigned { get; set; }
|
|
|
|
|
FieldInfo FieldInfo { get; set; }
|
|
|
|
|
PropertyInfo PropertyInfo { get; set; }
|
2017-10-26 16:41:14 +02:00
|
|
|
|
|
2017-11-03 13:13:09 +01:00
|
|
|
|
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;
|
|
|
|
|
}
|
2017-10-26 16:41:14 +02:00
|
|
|
|
|
2017-11-03 13:13:09 +01:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-10-26 16:41:14 +02:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|