V2 Implementation
parent
2431f10a8b
commit
8ded5ec2af
|
@ -1,2 +1,4 @@
|
|||
obj
|
||||
bin
|
||||
ln.types
|
||||
ln.logging
|
|
@ -0,0 +1,26 @@
|
|||
<Properties StartupConfiguration="{49FFBD9F-655E-4C74-A078-99B5E09059C6}|Default">
|
||||
<MonoDevelop.Ide.Workbench>
|
||||
<Pads>
|
||||
<Pad Id="ProjectPad">
|
||||
<State name="__root__">
|
||||
<Node name="sharp.json" expanded="True">
|
||||
<Node name="json.test" expanded="True" />
|
||||
<Node name="ln.json" expanded="True">
|
||||
<Node name="JSONParser.cs" selected="True" />
|
||||
</Node>
|
||||
<Node name="ln.types" expanded="True">
|
||||
<Node name="stream" expanded="True" />
|
||||
</Node>
|
||||
</Node>
|
||||
</State>
|
||||
</Pad>
|
||||
</Pads>
|
||||
</MonoDevelop.Ide.Workbench>
|
||||
<MonoDevelop.Ide.ItemProperties.json.test PreferredExecutionTarget="MonoDevelop.Default" />
|
||||
<MonoDevelop.Ide.DebuggingService.PinnedWatches />
|
||||
<MonoDevelop.Ide.Workspace ActiveConfiguration="Debug" />
|
||||
<MonoDevelop.Ide.DebuggingService.Breakpoints>
|
||||
<BreakpointStore />
|
||||
</MonoDevelop.Ide.DebuggingService.Breakpoints>
|
||||
<MultiItemStartupConfigurations />
|
||||
</Properties>
|
288
ByteParser.cs
288
ByteParser.cs
|
@ -1,288 +0,0 @@
|
|||
using System;
|
||||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
using sharp.extensions;
|
||||
using System.Globalization;
|
||||
|
||||
namespace sharp.json
|
||||
{
|
||||
public class ByteParser
|
||||
{
|
||||
private static ASCIIEncoding encoding = new ASCIIEncoding();
|
||||
|
||||
static System.Tuple<char,char>[] escapeCharacters = {
|
||||
System.Tuple.Create('\\','\\'),
|
||||
System.Tuple.Create('/','/'),
|
||||
System.Tuple.Create('"','"'),
|
||||
System.Tuple.Create('b','\b'),
|
||||
System.Tuple.Create('f','\f'),
|
||||
System.Tuple.Create('n','\n'),
|
||||
System.Tuple.Create('r','\r'),
|
||||
System.Tuple.Create('t','\t'),
|
||||
};
|
||||
|
||||
static List<char> numberScan = new List<char>(new char[] { '-', '0', '1', '2', '3', '4', '5', '7', '8', '9', '.','E','e' });
|
||||
|
||||
char[] buffer;
|
||||
int position;
|
||||
|
||||
public ByteParser(string source)
|
||||
{
|
||||
this.buffer = source.ToCharArray();
|
||||
this.position = 0;
|
||||
}
|
||||
|
||||
public char Peek(){
|
||||
//if (position >= buffer.Length){
|
||||
// return 0;
|
||||
//}
|
||||
return buffer[position];
|
||||
}
|
||||
|
||||
public string Peek(int len){
|
||||
return new String(buffer.Segment(position,len).Extend(len));
|
||||
}
|
||||
|
||||
|
||||
public char Read(){
|
||||
if (position < buffer.Length){
|
||||
return buffer[position++];
|
||||
}
|
||||
throw new Exception("End of buffer reached. No more characters available!");
|
||||
}
|
||||
public char[] Read(int len){
|
||||
if ((position) < buffer.Length){
|
||||
char[] r = buffer.Segment(position, len).Extend(len);
|
||||
position += r.Length;
|
||||
return r;
|
||||
}
|
||||
throw new Exception("End of buffer reached. No more characters available!");
|
||||
}
|
||||
|
||||
private Int64 parseInt64(){
|
||||
Int64 t = 0;
|
||||
char ch = Read();
|
||||
bool neg = false;
|
||||
if (ch == '-'){
|
||||
neg = true;
|
||||
ch = Read();
|
||||
}
|
||||
|
||||
if (!ch.isDigit()){
|
||||
throw new FormatException("JSON: Number format error");
|
||||
}
|
||||
|
||||
while (true){
|
||||
t *= 10;
|
||||
t += (int)(ch - '0');
|
||||
if (!Peek().isDigit()){
|
||||
break;
|
||||
}
|
||||
ch = Read();
|
||||
}
|
||||
|
||||
if (neg){
|
||||
t *= -1;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
public JSON parseNumber(){
|
||||
List<char> digits = new List<char>();
|
||||
|
||||
do
|
||||
{
|
||||
char n = (char)Peek();
|
||||
if (!numberScan.Contains(n)){
|
||||
break;
|
||||
}
|
||||
digits.Add(n);
|
||||
Read();
|
||||
} while (true);
|
||||
|
||||
string sv = new String(digits.ToArray());
|
||||
|
||||
if ((sv.IndexOf(".") > 0)||(sv.IndexOf("E") > 0)||(sv.IndexOf("e") > 0))
|
||||
{
|
||||
return new JSONNumber(double.Parse(sv,CultureInfo.InvariantCulture));
|
||||
} else {
|
||||
return new JSONNumber(Int64.Parse(sv));
|
||||
}
|
||||
|
||||
//Int64 i64 = parseInt64();
|
||||
|
||||
//if (Peek() == '.'){
|
||||
// Read();
|
||||
// Int64 dec = parseInt64();
|
||||
// int lg10 = (int)Math.Log10(dec);
|
||||
// i64 = i64 * lg10;
|
||||
// if (i64 < 0){
|
||||
// i64 -= dec;
|
||||
// } else {
|
||||
// i64 += dec;
|
||||
// }
|
||||
// return new JSONNumber(((double)i64) / (double)lg10 );
|
||||
//} else {
|
||||
// return new JSONNumber(i64);
|
||||
//}
|
||||
}
|
||||
|
||||
public JSON parseObject(){
|
||||
if (Read() != '{'){
|
||||
throw new FormatException("parser error: JSON Object should begin with '{'");
|
||||
}
|
||||
|
||||
JSONObject o = new JSONObject();
|
||||
|
||||
scanWhitespace();
|
||||
|
||||
if (Peek() == '}'){
|
||||
return o;
|
||||
} else {
|
||||
while (true){
|
||||
string name = parseStringInternal();
|
||||
|
||||
scanWhitespace();
|
||||
|
||||
if (Read() != ':'){
|
||||
throw new FormatException(String.Format("parser error: expected ':' but got '{0}'",buffer[position-1]));
|
||||
}
|
||||
|
||||
scanWhitespace();
|
||||
o[name] = parseValue();
|
||||
|
||||
scanWhitespace();
|
||||
|
||||
char n = Read();
|
||||
|
||||
if (n == '}'){
|
||||
break;
|
||||
}
|
||||
if (n == ','){
|
||||
scanWhitespace();
|
||||
continue;
|
||||
}
|
||||
throw new FormatException("parser error: expected ',' or '}' but got '"+n+"'");
|
||||
}
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
public JSON parseArray(){
|
||||
if (Read() != '['){
|
||||
throw new FormatException("parser error: JSON array should begin with '['");
|
||||
}
|
||||
|
||||
JSONArray o = new JSONArray();
|
||||
|
||||
scanWhitespace();
|
||||
|
||||
if (Peek() == ']'){
|
||||
return o;
|
||||
} else {
|
||||
while (true){
|
||||
o.Add(parseValue());
|
||||
|
||||
scanWhitespace();
|
||||
|
||||
char n = Read();
|
||||
|
||||
if (n == ']'){
|
||||
break;
|
||||
}
|
||||
if (n == ','){
|
||||
scanWhitespace();
|
||||
continue;
|
||||
}
|
||||
throw new FormatException(String.Format("parser error: expected ',' or ']' but got '{0}'",n));
|
||||
}
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
private string parseStringInternal(){
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
if (Read() != '"'){
|
||||
throw new FormatException(String.Format("JSON string must start with '\"' but got '{0}'",buffer[position-1]));
|
||||
}
|
||||
|
||||
while (Peek() != '"'){
|
||||
char ch = Read();
|
||||
sb.Append(ch);
|
||||
if (ch == '\\')
|
||||
{
|
||||
ch = Read();
|
||||
sb.Append(ch);
|
||||
}
|
||||
}
|
||||
Read();
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public JSON parseString(){
|
||||
return new JSONString(parseStringInternal());
|
||||
}
|
||||
|
||||
public JSON parseValue(){
|
||||
scanWhitespace();
|
||||
char peek = Peek();
|
||||
|
||||
switch (peek){
|
||||
case '{':
|
||||
return parseObject();
|
||||
case '[':
|
||||
return parseArray();
|
||||
case '"':
|
||||
return parseString();
|
||||
}
|
||||
|
||||
if ((peek >= '0' && peek <= '9') || (peek == '-')){
|
||||
return parseNumber();
|
||||
}
|
||||
|
||||
String p = Peek(4).ToLower();
|
||||
if (p.Equals("true")){
|
||||
position+=4;
|
||||
return JSONSpecial.True;
|
||||
}
|
||||
if (p.Equals("null")){
|
||||
position+=4;
|
||||
return JSONSpecial.Null;
|
||||
}
|
||||
p = Peek(5).ToLower();
|
||||
if (p.Equals("false")){
|
||||
position+=5;
|
||||
return JSONSpecial.False;
|
||||
}
|
||||
|
||||
throw new FormatException(String.Format("Could not parse source at character '{0}' at position {1}",Peek(),position));
|
||||
}
|
||||
|
||||
public JSON parse(){
|
||||
return parseValue();
|
||||
}
|
||||
|
||||
private int findNext(char c){
|
||||
int p = position;
|
||||
while (p < buffer.Length){
|
||||
if (buffer[p] == c){
|
||||
return p - position;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private int scanWhitespace(){
|
||||
while (position < buffer.Length){
|
||||
if (buffer[position] > 0x20){
|
||||
return position;
|
||||
}
|
||||
position++;
|
||||
}
|
||||
return position;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
202
JSON.cs
202
JSON.cs
|
@ -1,202 +0,0 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Reflection;
|
||||
using System.Collections;
|
||||
using System.Security.Cryptography;
|
||||
using System.CodeDom;
|
||||
using System.Globalization;
|
||||
|
||||
namespace sharp.json
|
||||
{
|
||||
public delegate object JSONActivationDelegate(Type t);
|
||||
|
||||
public abstract class JSON : IEnumerable<JSON>
|
||||
{
|
||||
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 object Object { 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 static implicit operator string(JSON json)
|
||||
{
|
||||
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 T To<T>()
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
public void WriteTo(String filename)
|
||||
{
|
||||
WriteTo(filename, false);
|
||||
}
|
||||
public void WriteTo(String filename,bool pretty)
|
||||
{
|
||||
using (FileStream fs = new FileStream(filename, FileMode.Create))
|
||||
{
|
||||
WriteTo(fs, pretty);
|
||||
fs.Close();
|
||||
}
|
||||
}
|
||||
|
||||
public static JSON ReadFrom(string filename)
|
||||
{
|
||||
return ReadFrom(filename, null);
|
||||
}
|
||||
|
||||
public static JSON ReadFrom(string filename, object defaultValue)
|
||||
{
|
||||
JSONParser parser = new JSONParser();
|
||||
string source = "";
|
||||
try
|
||||
{
|
||||
source = File.ReadAllText(filename);
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
return JSON.From(defaultValue);
|
||||
}
|
||||
return parser.Parse(source);
|
||||
}
|
||||
|
||||
public static JSON ReadFrom(string filename,JSON defaultValue){
|
||||
JSONParser parser = new JSONParser();
|
||||
string source = "";
|
||||
try
|
||||
{
|
||||
source = File.ReadAllText(filename);
|
||||
} catch (FileNotFoundException e){
|
||||
return defaultValue;
|
||||
}
|
||||
if (source.Equals(""))
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
return parser.Parse(source);
|
||||
}
|
||||
|
||||
public object Native(){
|
||||
switch (JSONType)
|
||||
{
|
||||
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;
|
||||
}
|
||||
throw new InvalidCastException(String.Format("Can't create native type of {0}",this.JSONType));
|
||||
}
|
||||
|
||||
|
||||
|
||||
public virtual IEnumerator<JSON> GetEnumerator()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return (IEnumerator)GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
134
JSONArray.cs
134
JSONArray.cs
|
@ -2,110 +2,56 @@ using System;
|
|||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace sharp.json
|
||||
namespace ln.json
|
||||
{
|
||||
public class JSONArray : JSON
|
||||
{
|
||||
public JSONArray()
|
||||
: base(JSONTypes.Array) { }
|
||||
public class JSONArray : JSONValue
|
||||
{
|
||||
public override IEnumerable<JSONValue> Children => Values;
|
||||
public override bool HasChildren => true;
|
||||
|
||||
public JSONArray(object[] init)
|
||||
: base(JSONTypes.Array)
|
||||
{
|
||||
foreach (object o in init)
|
||||
{
|
||||
this.values.Add(JSONConverter.From(o));
|
||||
}
|
||||
|
||||
}
|
||||
JSONValue[] Values
|
||||
{
|
||||
get => values.ToArray();
|
||||
set
|
||||
{
|
||||
values.Clear();
|
||||
values.AddRange(value);
|
||||
}
|
||||
}
|
||||
|
||||
List<JSON> values = new List<JSON>();
|
||||
List<JSONValue> values = new List<JSONValue>();
|
||||
|
||||
public override bool Boolean
|
||||
{
|
||||
get { return values.Count > 0; }
|
||||
}
|
||||
public JSONArray()
|
||||
: base(JSONValueType.ARRAY) { }
|
||||
|
||||
public override JSON this[int n]
|
||||
{
|
||||
get
|
||||
{
|
||||
return values[n];
|
||||
}
|
||||
set
|
||||
{
|
||||
values[n] = value;
|
||||
}
|
||||
}
|
||||
public override JSONValue this[int index] {
|
||||
get => values[index];
|
||||
set => values[index] = value;
|
||||
}
|
||||
|
||||
public override int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.values.Count;
|
||||
}
|
||||
}
|
||||
public JSONArray Add(JSONValue value){ values.Add(value); return this; }
|
||||
public JSONArray Remove(int index) { values.RemoveAt(index); return this; }
|
||||
|
||||
public override bool Contains(object o)
|
||||
{
|
||||
return this.values.Contains((JSON)o);
|
||||
}
|
||||
public override string ToString()
|
||||
{
|
||||
|
||||
public override void Add(JSON child)
|
||||
{
|
||||
this.values.Add(child);
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.Append('[');
|
||||
|
||||
public override void Remove(JSON child)
|
||||
{
|
||||
this.values.Remove(child);
|
||||
}
|
||||
IEnumerator<JSONValue> kenum = values.GetEnumerator();
|
||||
if (kenum.MoveNext())
|
||||
do
|
||||
{
|
||||
sb.Append(kenum.Current.ToString());
|
||||
|
||||
public override string[] prettyPrint()
|
||||
{
|
||||
List<string> lines = new List<string>();
|
||||
if (!kenum.MoveNext())
|
||||
break;
|
||||
sb.Append(',');
|
||||
} while (true);
|
||||
|
||||
lines.Add("[");
|
||||
sb.Append(']');
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
for (int i = 0; i < this.values.Count; i++)
|
||||
{
|
||||
JSON cv = this.values[i];
|
||||
string[] clines = cv.prettyPrint();
|
||||
|
||||
for (int n = 0; n < clines.Length; n++)
|
||||
{
|
||||
lines.Add(String.Format(" {0}{1}", clines[n], (n < clines.Length - 1) || (i == this.values.Count - 1) ? "" : ","));
|
||||
}
|
||||
}
|
||||
|
||||
lines.Add("]");
|
||||
|
||||
return lines.ToArray();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.Append("[");
|
||||
for (int n = 0; n < this.Count; n++)
|
||||
{
|
||||
sb.Append(this[n].ToString());
|
||||
if (n + 1 < this.Count)
|
||||
{
|
||||
sb.Append(",");
|
||||
}
|
||||
}
|
||||
sb.Append("]");
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public override IEnumerator<JSON> GetEnumerator()
|
||||
{
|
||||
return this.values.GetEnumerator();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
366
JSONConverter.cs
366
JSONConverter.cs
|
@ -1,366 +0,0 @@
|
|||
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) => (int)json.Integer },
|
||||
{ typeof(short), (t, json) => (short)json.Integer },
|
||||
{ typeof(long), (t, json) => json.Integer },
|
||||
{ typeof(uint), (t, json) => (uint)json.Integer },
|
||||
{ typeof(ushort), (t, json) => (ushort)json.Integer },
|
||||
{ typeof(ulong), (t, json) => (ulong)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);
|
||||
Type et = t.GetElementType();
|
||||
|
||||
JSONField jfield = t.GetCustomAttribute<JSONField>();
|
||||
if (!jfield.IsNull())
|
||||
{
|
||||
et = jfield.ConstructWithType;
|
||||
}
|
||||
|
||||
for (int n = 0; n < json.Count; n++)
|
||||
{
|
||||
a.SetValue(To(et ,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))
|
||||
{
|
||||
if (pi.GetIndexParameters().Length == 0){
|
||||
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)
|
||||
{
|
||||
if (PropertyInfo.SetMethod != 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 ((JSONField != null)&&(JSONField.ConstructWithType != null))
|
||||
{
|
||||
return JSONField.ConstructWithType;
|
||||
}
|
||||
if (PropertyInfo != null)
|
||||
{
|
||||
return PropertyInfo.PropertyType;
|
||||
}
|
||||
else if (FieldInfo != null)
|
||||
{
|
||||
return FieldInfo.FieldType;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
111
JSONNumber.cs
111
JSONNumber.cs
|
@ -1,94 +1,35 @@
|
|||
using System;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
namespace sharp.json
|
||||
namespace ln.json
|
||||
{
|
||||
public class JSONNumber: JSON
|
||||
{
|
||||
Int64 intValue;
|
||||
Double doubleValue;
|
||||
public class JSONNumber : JSONValue
|
||||
{
|
||||
readonly decimal decValue;
|
||||
|
||||
public JSONNumber()
|
||||
:base(JSONTypes.Number)
|
||||
{
|
||||
intValue = 0;
|
||||
doubleValue = Double.NaN;
|
||||
}
|
||||
public JSONNumber(Int64 i)
|
||||
:base(JSONTypes.Number)
|
||||
{
|
||||
intValue = i;
|
||||
doubleValue = Double.NaN;
|
||||
}
|
||||
public JSONNumber(Double d)
|
||||
:base(JSONTypes.Number)
|
||||
{
|
||||
intValue = (Int64)d;
|
||||
doubleValue = d;
|
||||
}
|
||||
public JSONNumber(int i)
|
||||
: this((long)i) { }
|
||||
|
||||
public override double Double
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!Double.IsNaN(doubleValue)){
|
||||
return doubleValue;
|
||||
} else {
|
||||
return (double)intValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
public JSONNumber(long integer)
|
||||
: base(JSONValueType.NUMBER)
|
||||
{
|
||||
decValue = new decimal(integer);
|
||||
}
|
||||
|
||||
public override long Integer
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!Double.IsNaN(doubleValue)){
|
||||
return (int)doubleValue;
|
||||
} else {
|
||||
return intValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
public JSONNumber(double doubleValue)
|
||||
: base(JSONValueType.NUMBER)
|
||||
{
|
||||
decValue = new Decimal(doubleValue);
|
||||
}
|
||||
public JSONNumber(decimal decValue)
|
||||
: base(JSONValueType.NUMBER)
|
||||
{
|
||||
this.decValue = decValue;
|
||||
}
|
||||
|
||||
public override string String
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!Double.IsNaN(doubleValue))
|
||||
{
|
||||
return doubleValue.ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
return intValue.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public override string[] prettyPrint()
|
||||
{
|
||||
return new string[] { ToString() };
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if (Double.IsNaN(doubleValue))
|
||||
{
|
||||
return this.intValue.ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.doubleValue.ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsInteger(){
|
||||
return Double.IsNaN(doubleValue);
|
||||
}
|
||||
|
||||
}
|
||||
public override string ToString()
|
||||
{
|
||||
return decValue.ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
112
JSONObject.cs
112
JSONObject.cs
|
@ -1,86 +1,60 @@
|
|||
using System;
|
||||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
using sharp.extensions;
|
||||
using System.Reflection;
|
||||
using System.Linq;
|
||||
using ln.types.btree;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace sharp.json
|
||||
namespace ln.json
|
||||
{
|
||||
public class JSONObject : JSON
|
||||
public class JSONObject : JSONValue
|
||||
{
|
||||
public IEnumerable<string> Keys => values.Keys;
|
||||
|
||||
public override IEnumerable<JSONValue> Children => values.Values;
|
||||
public override bool HasChildren => true;
|
||||
|
||||
BTree<string, JSONValue> values = new BTree<string, JSONValue>();
|
||||
|
||||
public JSONObject()
|
||||
:base(JSONTypes.Object){}
|
||||
:base(JSONValueType.OBJECT){}
|
||||
|
||||
private Dictionary<string, JSON> values = new Dictionary<string, JSON>();
|
||||
public override JSONValue this[string property]
|
||||
{
|
||||
get => values[property];
|
||||
set => values[property] = value;
|
||||
}
|
||||
|
||||
public override JSON this[string name]
|
||||
{
|
||||
get { return this.values[name]; }
|
||||
set { this.values[name] = value; }
|
||||
}
|
||||
public JSONObject Add(string propertyName,JSONValue value)
|
||||
{
|
||||
values[propertyName] = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
public override int Count
|
||||
{
|
||||
get { return this.values.Count; }
|
||||
}
|
||||
public override string ToString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.Append('{');
|
||||
|
||||
public override bool Boolean
|
||||
{
|
||||
get { return this.values.Count > 0; }
|
||||
}
|
||||
IEnumerator<string> kenum = values.Keys.GetEnumerator();
|
||||
if (kenum.MoveNext())
|
||||
do
|
||||
{
|
||||
sb.Append('"');
|
||||
sb.Append(kenum.Current);
|
||||
sb.Append('"');
|
||||
sb.Append(':');
|
||||
sb.Append(values[kenum.Current].ToString());
|
||||
|
||||
public override bool Contains(object o)
|
||||
{
|
||||
return this.values.ContainsKey((string)o);
|
||||
}
|
||||
if (!kenum.MoveNext())
|
||||
break;
|
||||
sb.Append(',');
|
||||
} while (true);
|
||||
|
||||
sb.Append('}');
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
|
||||
public override string[] prettyPrint()
|
||||
{
|
||||
List<string> lines = new List<string>();
|
||||
lines.Add("{");
|
||||
|
||||
string[] keys = this.values.Keys.ToArray();
|
||||
|
||||
for (int n=0;n<keys.Length;n++)
|
||||
{
|
||||
string[] clines = this[keys[n]].prettyPrint();
|
||||
|
||||
lines.Add(String.Format(" {0} : {1}",new JSONString(keys[n]),clines[0]));
|
||||
foreach (string cline in clines.Segment(1)){
|
||||
lines.Add(String.Format(" {0}",cline));
|
||||
}
|
||||
|
||||
if (n < keys.Length-1){
|
||||
lines[lines.Count - 1] += ",";
|
||||
}
|
||||
}
|
||||
lines.Add("}");
|
||||
return lines.ToArray();
|
||||
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.Append("{");
|
||||
|
||||
string[] keys = this.values.Keys.ToArray();
|
||||
|
||||
for (int n=0;n<keys.Length;n++)
|
||||
{
|
||||
sb.Append(new JSONString(keys[n]).ToString());
|
||||
sb.Append(":");
|
||||
sb.Append(this[keys[n]].ToString());
|
||||
if (n+1 < keys.Length){
|
||||
sb.Append(",");
|
||||
}
|
||||
}
|
||||
sb.Append("}");
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
503
JSONParser.cs
503
JSONParser.cs
|
@ -1,321 +1,236 @@
|
|||
using System;
|
||||
using sharp.parser;
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
using System.Globalization;
|
||||
using System.Net.Mime;
|
||||
// /**
|
||||
// * File: JSONParser.cs
|
||||
// * Author: haraldwolff
|
||||
// *
|
||||
// * This file and it's content is copyrighted by the Author and / or copyright holder.
|
||||
// * Any use wihtout proper permission is illegal and may lead to legal actions.
|
||||
// *
|
||||
// *
|
||||
// **/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace sharp.json
|
||||
using ln.types;
|
||||
using ln.types.stream;
|
||||
using System.Text;
|
||||
using System.Globalization;
|
||||
namespace ln.json
|
||||
{
|
||||
public class JSONParser : Parser<JSON>
|
||||
{
|
||||
delegate JSON ParseObjectDelegate(TokenQueue tokens);
|
||||
public class JSONParser
|
||||
{
|
||||
static char[] chNull = new char[] { 'n', 'u', 'l', 'l' };
|
||||
static char[] chTrue = new char[] { 't', 'r', 'u', 'e' };
|
||||
static char[] chFalse = new char[] { 'f', 'a', 'l', 's', 'e' };
|
||||
|
||||
Dictionary<TokenDefinition, ParseObjectDelegate> parserDelegates = new Dictionary<TokenDefinition, ParseObjectDelegate>();
|
||||
|
||||
public JSONParser()
|
||||
:base(tokenDefinitions)
|
||||
{
|
||||
parserDelegates.Add(tString,parseString);
|
||||
parserDelegates.Add(tNumber,parseNumber);
|
||||
parserDelegates.Add(tObjectOpen,parseObject);
|
||||
parserDelegates.Add(tArrayOpen,parseArray);
|
||||
parserDelegates.Add(tTrue,parseTrue);
|
||||
parserDelegates.Add(tFalse,parseFalse);
|
||||
parserDelegates.Add(tNull,parseNull);
|
||||
}
|
||||
|
||||
protected override JSON ParseTokens(Token[] tokens)
|
||||
{
|
||||
TokenQueue qtoken = new TokenQueue();
|
||||
foreach (Token t in tokens){
|
||||
if (t.Definition != tWhiteSpace){
|
||||
qtoken.Enqueue(t);
|
||||
}
|
||||
}
|
||||
return parseValue(qtoken);
|
||||
}
|
||||
|
||||
private JSON parseValue(TokenQueue tokens){
|
||||
foreach (TokenDefinition tdef in this.parserDelegates.Keys){
|
||||
if (tdef == tokens.Peek().Definition){
|
||||
return this.parserDelegates[tokens.Peek().Definition](tokens);
|
||||
}
|
||||
}
|
||||
throw new Exception(String.Format("Parser got unexpected token: {0}", tokens.Peek().ToString()));
|
||||
}
|
||||
|
||||
JSON parseString(TokenQueue tokens){
|
||||
Token t = tokens.Expect(tString);
|
||||
return new JSONString(t.Value.Substring(1, t.Value.Length - 2));
|
||||
}
|
||||
|
||||
JSON parseNumber(TokenQueue tokens)
|
||||
{
|
||||
Token t = tokens.Expect(tNumber);
|
||||
Double dv = double.Parse(t.Value,CultureInfo.InvariantCulture);
|
||||
return new JSONNumber(dv);
|
||||
}
|
||||
|
||||
JSON parseObject(TokenQueue tokens)
|
||||
{
|
||||
Token t = tokens.Expect(tObjectOpen);
|
||||
JSONObject jo = new JSONObject();
|
||||
|
||||
if (tokens.Peek().Definition == tObjectClose){
|
||||
tokens.Dequeue();
|
||||
return jo;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
JSONString js = (JSONString)parseString(tokens);
|
||||
|
||||
tokens.Expect(tColon);
|
||||
|
||||
JSON json = parseValue(tokens);
|
||||
jo[js.String] = json;
|
||||
|
||||
t = tokens.Expect(tObjectClose, tComma);
|
||||
|
||||
if (t.Definition == tObjectClose){
|
||||
break;
|
||||
}
|
||||
} while (true);
|
||||
|
||||
return jo;
|
||||
}
|
||||
|
||||
JSON parseArray(TokenQueue tokens)
|
||||
{
|
||||
Token t = tokens.Expect(tArrayOpen);
|
||||
JSONArray ja = new JSONArray();
|
||||
|
||||
if (tokens.Peek().Definition == tArrayClose)
|
||||
{
|
||||
tokens.Dequeue();
|
||||
return ja;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
JSON json = parseValue(tokens);
|
||||
ja.Add(json);
|
||||
|
||||
t = tokens.Expect(tArrayClose, tComma);
|
||||
|
||||
if (t.Definition == tArrayClose)
|
||||
{
|
||||
break;
|
||||
}
|
||||
} while (true);
|
||||
|
||||
return ja;
|
||||
}
|
||||
|
||||
JSON parseTrue(TokenQueue tokens)
|
||||
{
|
||||
if (tokens.Peek().Definition == tTrue){
|
||||
Token t = tokens.Dequeue();
|
||||
return JSONSpecial.True;
|
||||
}
|
||||
throw new Exception("Unexpected Token: " + tokens.Peek());
|
||||
}
|
||||
JSON parseFalse(TokenQueue tokens)
|
||||
{
|
||||
if (tokens.Peek().Definition == tFalse){
|
||||
Token t = tokens.Dequeue();
|
||||
return JSONSpecial.False;
|
||||
}
|
||||
throw new Exception("Unexpected Token: " + tokens.Peek());
|
||||
}
|
||||
JSON parseNull(TokenQueue tokens)
|
||||
{
|
||||
if (tokens.Peek().Definition == tNull){
|
||||
Token t = tokens.Dequeue();
|
||||
return JSONSpecial.Null;
|
||||
}
|
||||
throw new Exception("Unexpected Token: " + tokens.Peek());
|
||||
}
|
||||
public static JSONValue Parse(String jsonSource)
|
||||
{
|
||||
CharStream chars = new CharStream(jsonSource);
|
||||
return ParseValue(chars);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Für alle Parser Methoden welche als Parameter ein CharStream erhalten
|
||||
* gilt folgendes:
|
||||
*
|
||||
* - CharStream.Current zeitg auf das erste Zeichen,
|
||||
* welches interpretiert werden soll
|
||||
* - Bei Rücksprung zeigt CharStream.Current auf das erste zeichen,
|
||||
* welches nicht mehr zum aktuellen Wert gehört und kein Whitespace
|
||||
* ist
|
||||
*
|
||||
**/
|
||||
|
||||
static bool initializer = initialize();
|
||||
static JSONValue ParseValue(CharStream chars)
|
||||
{
|
||||
chars.Skip(char.IsWhiteSpace);
|
||||
switch (chars.Current)
|
||||
{
|
||||
case '"':
|
||||
return parseString(chars);
|
||||
case 't':
|
||||
return parseTrue(chars);
|
||||
case 'f':
|
||||
return parseFalse(chars);
|
||||
case 'n':
|
||||
return parseNull(chars);
|
||||
case '[':
|
||||
return parseArray(chars);
|
||||
case '{':
|
||||
return parseObject(chars);
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
case '-':
|
||||
return parseNumber(chars);
|
||||
default:
|
||||
throw new FormatException(String.Format("Unexpected character: {0} [ 0x{0:x4} ]", chars.Current));
|
||||
}
|
||||
}
|
||||
|
||||
static TokenDefinition[] tokenDefinitions;
|
||||
static JSONString parseString(CharStream chars)
|
||||
{
|
||||
if (chars.Current != '"')
|
||||
throw new FormatException("Unexpected character");
|
||||
|
||||
static CharGroup eE = new CharGroup(new char[] { 'e', 'E' } );
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
|
||||
static LexerPathSegment null_ll;
|
||||
static LexerPathSegment null_l;
|
||||
static LexerPathSegment null_u;
|
||||
static LexerPathSegment null_n;
|
||||
chars.MoveNext();
|
||||
while (chars.Current != '"')
|
||||
{
|
||||
stringBuilder.Append(chars.Current);
|
||||
if (chars.Current == '\\')
|
||||
{
|
||||
chars.MoveNext();
|
||||
stringBuilder.Append(chars.Current);
|
||||
}
|
||||
chars.MoveNext();
|
||||
}
|
||||
|
||||
static LexerPathSegment true_e;
|
||||
static LexerPathSegment true_u;
|
||||
static LexerPathSegment true_r;
|
||||
static LexerPathSegment true_t;
|
||||
chars.TryNext();
|
||||
chars.Skip(char.IsWhiteSpace);
|
||||
|
||||
static LexerPathSegment false_e;
|
||||
static LexerPathSegment false_s;
|
||||
static LexerPathSegment false_l;
|
||||
static LexerPathSegment false_a;
|
||||
static LexerPathSegment false_f;
|
||||
return new JSONString(JSONString.Unescape(stringBuilder.ToString()));
|
||||
}
|
||||
static JSONNumber parseNumber(CharStream chars)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
static LexerPathSegment ws;
|
||||
if (chars.Current == '-')
|
||||
{
|
||||
sb.Append(chars.Current);
|
||||
chars.MoveNext();
|
||||
}
|
||||
sb.Append(chars.Read(char.IsDigit));
|
||||
if (chars.Current == '.')
|
||||
{
|
||||
sb.Append('.');
|
||||
chars.MoveNext();
|
||||
sb.Append(chars.Read(char.IsDigit));
|
||||
}
|
||||
if ((chars.Current == 'e')|| (chars.Current == 'E'))
|
||||
{
|
||||
sb.Append('e');
|
||||
if ((chars.Current == '-')|| (chars.Current == '+'))
|
||||
{
|
||||
sb.Append(chars.Current);
|
||||
chars.MoveNext();
|
||||
}
|
||||
sb.Append(chars.Read(char.IsDigit));
|
||||
}
|
||||
|
||||
static TokenDefinition tNumber;
|
||||
static TokenDefinition tString;
|
||||
static TokenDefinition tColon;
|
||||
static TokenDefinition tComma;
|
||||
static TokenDefinition tObjectOpen;
|
||||
static TokenDefinition tObjectClose;
|
||||
static TokenDefinition tArrayOpen;
|
||||
static TokenDefinition tArrayClose;
|
||||
static TokenDefinition tTrue;
|
||||
static TokenDefinition tFalse;
|
||||
static TokenDefinition tNull;
|
||||
static TokenDefinition tWhiteSpace;
|
||||
chars.Skip(char.IsWhiteSpace);
|
||||
return new JSONNumber(decimal.Parse(sb.ToString(),CultureInfo.InvariantCulture));
|
||||
}
|
||||
static JSONArray parseArray(CharStream chars)
|
||||
{
|
||||
if (chars.Current != '[')
|
||||
throw new FormatException("Unexpected character");
|
||||
|
||||
static private bool initialize(){
|
||||
eE = new CharGroup(new char[] { 'e', 'E' });
|
||||
JSONArray array = new JSONArray();
|
||||
|
||||
null_ll = new LexerPathSegment('l', true);
|
||||
null_l = new LexerPathSegment('l', null_ll);
|
||||
null_u = new LexerPathSegment('u', null_l);
|
||||
null_n = new LexerPathSegment('n', null_u);
|
||||
chars.MoveNext();
|
||||
while (chars.Current != ']')
|
||||
{
|
||||
array.Add(ParseValue(chars));
|
||||
if (chars.Current == ',')
|
||||
{
|
||||
chars.MoveNext();
|
||||
chars.Skip(char.IsWhiteSpace);
|
||||
}
|
||||
}
|
||||
|
||||
true_e = new LexerPathSegment('e', true);
|
||||
true_u = new LexerPathSegment('u', true_e);
|
||||
true_r = new LexerPathSegment('r', true_u);
|
||||
true_t = new LexerPathSegment('t', true_r);
|
||||
chars.TryNext();
|
||||
chars.Skip(char.IsWhiteSpace);
|
||||
|
||||
false_e = new LexerPathSegment('e', true);
|
||||
false_s = new LexerPathSegment('s', false_e);
|
||||
false_l = new LexerPathSegment('l', false_s);
|
||||
false_a = new LexerPathSegment('a', false_l);
|
||||
false_f = new LexerPathSegment('f', false_a);
|
||||
return array;
|
||||
}
|
||||
static JSONObject parseObject(CharStream chars)
|
||||
{
|
||||
if (chars.Current != '{')
|
||||
throw new FormatException("Unexpected character");
|
||||
|
||||
ws = new LexerPathSegment(CharGroup.WS, true);
|
||||
ws.AddFollower(ws);
|
||||
JSONObject o = new JSONObject();
|
||||
|
||||
tNumber = new TokenDefinition("JSON.number", initializeNumberHead());
|
||||
tString = new TokenDefinition("JSON.string", initializeStringHead());
|
||||
tColon = new TokenDefinition("JSON.colon", new LexerPathSegment(':',true));
|
||||
tComma = new TokenDefinition("JSON.comma", new LexerPathSegment(',',true));
|
||||
tObjectOpen = new TokenDefinition("JSON.obj.open", new LexerPathSegment('{',true));
|
||||
tObjectClose = new TokenDefinition("JSON.obj.close", new LexerPathSegment('}',true));
|
||||
tArrayOpen = new TokenDefinition("JSON.array.open", new LexerPathSegment('[',true));
|
||||
tArrayClose = new TokenDefinition("JSON.array.close", new LexerPathSegment(']',true));
|
||||
tTrue = new TokenDefinition("JSON.true", true_t);
|
||||
tFalse = new TokenDefinition("JSON.false", false_f);
|
||||
tNull = new TokenDefinition("JSON.null", null_n);
|
||||
tWhiteSpace = new TokenDefinition("JSON.WhiteSpace",ws);
|
||||
chars.MoveNext();
|
||||
chars.Skip(char.IsWhiteSpace);
|
||||
|
||||
tokenDefinitions = new TokenDefinition[]{
|
||||
tWhiteSpace,
|
||||
tNumber,
|
||||
tString,
|
||||
tColon,
|
||||
tComma,
|
||||
tObjectOpen,
|
||||
tObjectClose,
|
||||
tArrayOpen,
|
||||
tArrayClose,
|
||||
tTrue,
|
||||
tFalse,
|
||||
tNull
|
||||
};
|
||||
while (chars.Current != '}')
|
||||
{
|
||||
JSONString s = parseString(chars);
|
||||
if (chars.Current != ':')
|
||||
throw new FormatException("expected :");
|
||||
chars.MoveNext();
|
||||
o.Add(s.Value, ParseValue(chars));
|
||||
|
||||
if (chars.Current == ',')
|
||||
{
|
||||
chars.MoveNext();
|
||||
chars.Skip(char.IsWhiteSpace);
|
||||
}
|
||||
}
|
||||
|
||||
chars.TryNext();
|
||||
chars.Skip(char.IsWhiteSpace);
|
||||
|
||||
return o;
|
||||
}
|
||||
static JSONTrue parseTrue(CharStream chars)
|
||||
{
|
||||
char[] ch = new char[4];
|
||||
for (int n = 0; n < ch.Length; n++)
|
||||
{
|
||||
ch[n] = chars.Current;
|
||||
chars.MoveNext();
|
||||
}
|
||||
if (ch.AreEqual(chTrue))
|
||||
{
|
||||
chars.Skip(char.IsWhiteSpace);
|
||||
return JSONTrue.Instance;
|
||||
}
|
||||
|
||||
|
||||
throw new FormatException();
|
||||
}
|
||||
static JSONFalse parseFalse(CharStream chars)
|
||||
{
|
||||
char[] ch = new char[5];
|
||||
for (int n = 0; n < ch.Length; n++)
|
||||
{
|
||||
ch[n] = chars.Current;
|
||||
chars.MoveNext();
|
||||
}
|
||||
if (ch.AreEqual(chFalse))
|
||||
{
|
||||
chars.Skip(char.IsWhiteSpace);
|
||||
return JSONFalse.Instance;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
throw new FormatException();
|
||||
}
|
||||
static JSONNull parseNull(CharStream chars)
|
||||
{
|
||||
char[] ch = new char[4];
|
||||
for (int n=0;n<ch.Length;n++)
|
||||
{
|
||||
ch[n] = chars.Current;
|
||||
chars.MoveNext();
|
||||
}
|
||||
if (ch.AreEqual(chNull))
|
||||
{
|
||||
chars.Skip(char.IsWhiteSpace);
|
||||
return JSONNull.Instance;
|
||||
}
|
||||
|
||||
|
||||
static private LexerPathSegment initializeStringHead(){
|
||||
LexerPathSegment head = new LexerPathSegment('\"');
|
||||
LexerPathSegment finish = new LexerPathSegment('\"',true);
|
||||
LexerPathSegment backslash = new LexerPathSegment('\\');
|
||||
LexerPathSegment control = new LexerPathSegment(new char[] { '\"','\\','/','b','f','n','r','t'} );
|
||||
LexerPathSegment u4 = new LexerPathSegment(CharGroup.hexdigits);
|
||||
LexerPathSegment u3 = new LexerPathSegment(CharGroup.hexdigits,u4);
|
||||
LexerPathSegment u2 = new LexerPathSegment(CharGroup.hexdigits,u3);
|
||||
LexerPathSegment u1 = new LexerPathSegment(CharGroup.hexdigits,u2);
|
||||
LexerPathSegment ucontrol = new LexerPathSegment('u',u1);
|
||||
|
||||
CharGroup anyChar = new CharGroup((char)0x20, (char)0xff) - backslash.CharGroup - finish.CharGroup;
|
||||
LexerPathSegment any = new LexerPathSegment(anyChar);
|
||||
|
||||
head.AddFollower(finish);
|
||||
head.AddFollower(any);
|
||||
head.AddFollower(backslash);
|
||||
|
||||
any.AddFollower(any);
|
||||
any.AddFollower(backslash);
|
||||
any.AddFollower(finish);
|
||||
|
||||
backslash.AddFollower(control);
|
||||
backslash.AddFollower(ucontrol);
|
||||
|
||||
control.AddFollower(any);
|
||||
control.AddFollower(backslash);
|
||||
control.AddFollower(finish);
|
||||
|
||||
u4.AddFollower(any);
|
||||
u4.AddFollower(backslash);
|
||||
u4.AddFollower(finish);
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
static private LexerPathSegment initializeNumberHead()
|
||||
{
|
||||
LexerPathSegment head = new LexerPathSegment();
|
||||
LexerPathSegment minus = new LexerPathSegment(CharGroup.minus);
|
||||
LexerPathSegment zero = new LexerPathSegment('0',true);
|
||||
LexerPathSegment d19 = new LexerPathSegment('1', '9', true);
|
||||
LexerPathSegment digit_a = new LexerPathSegment(CharGroup.digit,true);
|
||||
LexerPathSegment digit_b = new LexerPathSegment(CharGroup.digit,true);
|
||||
LexerPathSegment digit_c = new LexerPathSegment(CharGroup.digit,true);
|
||||
LexerPathSegment dot = new LexerPathSegment('.');
|
||||
LexerPathSegment ee = new LexerPathSegment(eE);
|
||||
LexerPathSegment eminus = new LexerPathSegment(CharGroup.minus);
|
||||
LexerPathSegment plusminus = new LexerPathSegment(CharGroup.plusminus);
|
||||
|
||||
head.AddFollower(minus);
|
||||
head.AddFollower(zero);
|
||||
head.AddFollower(d19);
|
||||
|
||||
minus.AddFollower(zero);
|
||||
minus.AddFollower(d19);
|
||||
|
||||
zero.AddFollower(dot);
|
||||
zero.AddFollower(ee);
|
||||
|
||||
d19.AddFollower(digit_a);
|
||||
d19.AddFollower(dot);
|
||||
d19.AddFollower(ee);
|
||||
|
||||
digit_a.AddFollower(digit_a);
|
||||
digit_a.AddFollower(dot);
|
||||
digit_a.AddFollower(ee);
|
||||
|
||||
dot.AddFollower(digit_b);
|
||||
|
||||
digit_b.AddFollower(digit_b);
|
||||
digit_b.AddFollower(ee);
|
||||
|
||||
ee.AddFollower(digit_c);
|
||||
ee.AddFollower(plusminus);
|
||||
|
||||
plusminus.AddFollower(digit_c);
|
||||
|
||||
digit_c.AddFollower(digit_c);
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
}
|
||||
throw new FormatException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
using System;
|
||||
namespace sharp.json
|
||||
{
|
||||
public static class JSONSerializer
|
||||
{
|
||||
|
||||
public static void Apply(JSON json,Object o){
|
||||
Type t = o.GetType();
|
||||
|
||||
if (t.IsPrimitive){
|
||||
ApplyPrimitive(json,o);
|
||||
} else {
|
||||
ApplyClass(json, o);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ApplyPrimitive(JSON json,Object o){
|
||||
|
||||
}
|
||||
|
||||
public static void ApplyClass(JSON json,Object o){
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -1,53 +1,23 @@
|
|||
using System;
|
||||
namespace sharp.json
|
||||
namespace ln.json
|
||||
{
|
||||
public class JSONSpecial: JSON
|
||||
{
|
||||
public static readonly JSON True = new JSONSpecial(JSONTypes.True);
|
||||
public static readonly JSON False = new JSONSpecial(JSONTypes.False);
|
||||
public static readonly JSON Null = new JSONSpecial(JSONTypes.Null);
|
||||
public class JSONTrue : JSONValue
|
||||
{
|
||||
public static JSONTrue Instance { get; } = new JSONTrue();
|
||||
private JSONTrue() : base(JSONValueType.TRUE) { }
|
||||
public override string ToString() => "true";
|
||||
}
|
||||
public class JSONFalse : JSONValue
|
||||
{
|
||||
public static JSONFalse Instance { get; } = new JSONFalse();
|
||||
private JSONFalse() : base(JSONValueType.FALSE) { }
|
||||
public override string ToString() => "false";
|
||||
}
|
||||
public class JSONNull : JSONValue
|
||||
{
|
||||
public static JSONNull Instance { get; } = new JSONNull();
|
||||
private JSONNull() : base(JSONValueType.NULL) { }
|
||||
public override string ToString() => "null";
|
||||
}
|
||||
|
||||
private JSONSpecial(JSONTypes type)
|
||||
:base(type)
|
||||
{
|
||||
}
|
||||
|
||||
public override string[] prettyPrint()
|
||||
{
|
||||
return new string[] { ToString() };
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
switch (JSONType){
|
||||
case JSONTypes.Null:
|
||||
return "null";
|
||||
case JSONTypes.True:
|
||||
return "true";
|
||||
case JSONTypes.False:
|
||||
return "false";
|
||||
}
|
||||
throw new NotImplementedException("JSON Special Type badly wrong....");
|
||||
}
|
||||
|
||||
public override bool Boolean
|
||||
{
|
||||
get
|
||||
{
|
||||
return this == True;
|
||||
}
|
||||
}
|
||||
|
||||
public override string String
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this == Null){
|
||||
return null;
|
||||
}
|
||||
return base.String;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
122
JSONString.cs
122
JSONString.cs
|
@ -1,10 +1,9 @@
|
|||
using System;
|
||||
using System.Text;
|
||||
using sharp.extensions;
|
||||
|
||||
namespace sharp.json
|
||||
namespace ln.json
|
||||
{
|
||||
public class JSONString : JSON
|
||||
public class JSONString : JSONValue
|
||||
{
|
||||
static System.Tuple<char,char>[] escapeCharacters = {
|
||||
System.Tuple.Create('\\','\\'),
|
||||
|
@ -17,73 +16,45 @@ namespace sharp.json
|
|||
System.Tuple.Create('t','\t'),
|
||||
};
|
||||
|
||||
string value;
|
||||
public string Value { get; private set; }
|
||||
|
||||
public JSONString()
|
||||
:base(JSONTypes.String)
|
||||
public JSONString(String value)
|
||||
:base(JSONValueType.STRING)
|
||||
{
|
||||
this.value = "";
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public JSONString(String value)
|
||||
:base(JSONTypes.String)
|
||||
{
|
||||
this.value = value;
|
||||
}
|
||||
public override string ToString()
|
||||
{
|
||||
return String.Format("\"{0}\"", Escape(Value));
|
||||
}
|
||||
|
||||
public override string String
|
||||
{
|
||||
get { return this.value; }
|
||||
}
|
||||
|
||||
public override double Double
|
||||
{
|
||||
get { return Double.Parse(this.value); }
|
||||
}
|
||||
|
||||
public override long Integer
|
||||
{
|
||||
get { return long.Parse(this.value); }
|
||||
}
|
||||
|
||||
|
||||
public override string[] prettyPrint()
|
||||
{
|
||||
return new string[] { ToString() };
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return String.Format("\"{0}\"",escape(this.value));
|
||||
}
|
||||
|
||||
public static string escape(string source){
|
||||
public static string Escape(string source){
|
||||
StringBuilder sb = new StringBuilder();
|
||||
foreach (char ch in source){
|
||||
if ((ch >= 0x20) && (ch < 128)){
|
||||
sb.Append(ch);
|
||||
} else if (ch < 0x20){
|
||||
foreach (System.Tuple<char,char> repl in escapeCharacters){
|
||||
if (repl.Item2 == ch){
|
||||
sb.Append("\\");
|
||||
sb.Append(repl.Item1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int iv = (int)ch;
|
||||
sb.Append("\\u");
|
||||
sb.Append("____");
|
||||
Console.WriteLine("JSON WARNING: UNICODE ESCAPE SEQUENCES ARE NOT IMPLEMENTED YET");
|
||||
}
|
||||
if ((ch >= 0x20) && (ch < 128)) {
|
||||
sb.Append(ch);
|
||||
} else if (ch < 0x20) {
|
||||
foreach (System.Tuple<char, char> repl in escapeCharacters) {
|
||||
if (repl.Item2 == ch) {
|
||||
sb.Append("\\");
|
||||
sb.Append(repl.Item1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
byte[] bytes = BitConverter.GetBytes((int)ch);
|
||||
sb.Append("\\u");
|
||||
sb.AppendFormat("{0:x2}{1:x2}", bytes[1], bytes[0]);
|
||||
}
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public static string unescape(string source)
|
||||
public static string Unescape(string jsonString)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
CharEnumerator ce = source.GetEnumerator();
|
||||
CharEnumerator ce = jsonString.GetEnumerator();
|
||||
char[] hex = new char[4];
|
||||
|
||||
while (ce.MoveNext()){
|
||||
|
@ -91,23 +62,26 @@ namespace sharp.json
|
|||
if (ce.Current == '\\'){
|
||||
ce.MoveNext();
|
||||
|
||||
foreach (System.Tuple<char, char> repl in escapeCharacters)
|
||||
{
|
||||
if (repl.Item1 == ce.Current)
|
||||
{
|
||||
sb.Append(repl.Item2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ce.Current == 'u'){
|
||||
for (int n = 0; n < 4;n++){
|
||||
ce.MoveNext();
|
||||
hex[3 - n] = ce.Current;
|
||||
}
|
||||
sb.Append((char)( HexString.toBytes(hex).toUInt32()[0] ));
|
||||
}
|
||||
|
||||
if (ce.Current == 'u')
|
||||
{
|
||||
for (int n = 0; n < 4; n++)
|
||||
{
|
||||
ce.MoveNext();
|
||||
hex[3 - n] = ce.Current;
|
||||
}
|
||||
sb.Append((char)Convert.ToInt16(new String(hex),16));
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (System.Tuple<char, char> repl in escapeCharacters)
|
||||
{
|
||||
if (repl.Item1 == ce.Current)
|
||||
{
|
||||
sb.Append(repl.Item2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
sb.Append(ce.Current);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
using System;
|
||||
namespace sharp.json
|
||||
namespace ln.json
|
||||
{
|
||||
public enum JSONTypes
|
||||
{
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
// /**
|
||||
// * File: JSONValue.cs
|
||||
// * Author: haraldwolff
|
||||
// *
|
||||
// * This file and it's content is copyrighted by the Author and / or copyright holder.
|
||||
// * Any use wihtout proper permission is illegal and may lead to legal actions.
|
||||
// *
|
||||
// *
|
||||
// **/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
namespace ln.json
|
||||
{
|
||||
public enum JSONValueType
|
||||
{
|
||||
NULL, OBJECT, ARRAY, STRING, NUMBER, TRUE, FALSE
|
||||
}
|
||||
public abstract class JSONValue
|
||||
{
|
||||
public JSONValueType ValueType { get; private set; }
|
||||
|
||||
public virtual bool HasChildren => false;
|
||||
public virtual IEnumerable<JSONValue> Children => throw new NotSupportedException();
|
||||
|
||||
public JSONValue(JSONValueType valueType)
|
||||
{
|
||||
ValueType = valueType;
|
||||
}
|
||||
|
||||
public virtual JSONValue this[string property]
|
||||
{
|
||||
get => throw new NotSupportedException();
|
||||
set => throw new NotSupportedException();
|
||||
}
|
||||
public virtual JSONValue this[int index]
|
||||
{
|
||||
get => throw new NotSupportedException();
|
||||
set => throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override string ToString() => throw new NotImplementedException();
|
||||
}
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
using System;
|
||||
using sharp.extensions;
|
||||
using System.Net;
|
||||
using sharp.webclient;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace sharp.json
|
||||
{
|
||||
public class JSONWebRequest
|
||||
{
|
||||
private static JSONParser jsonParser = new JSONParser();
|
||||
|
||||
public static JSON Call(string url){
|
||||
return Call(url, null);
|
||||
}
|
||||
|
||||
public static JSON Call(string url, JSON request)
|
||||
{
|
||||
return Call(url, request, null);
|
||||
}
|
||||
|
||||
public static JSON Call(string url, JSON request, IDictionary<string,string> headers)
|
||||
{
|
||||
HttpRequest req = new HttpRequest(url);
|
||||
if (request != null){
|
||||
byte[] rbody = request.ToString().toBytes();
|
||||
req.RequestStream.Write(rbody,0,rbody.Length);
|
||||
}
|
||||
|
||||
if (headers != null)
|
||||
{
|
||||
foreach (string hname in headers.Keys)
|
||||
{
|
||||
req.setHeader(hname, headers[hname]);
|
||||
}
|
||||
}
|
||||
|
||||
HttpResponse response = req.Send();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -4,7 +4,7 @@ using System.Runtime.CompilerServices;
|
|||
// Information about this assembly is defined by the following attributes.
|
||||
// Change them to the values specific to your project.
|
||||
|
||||
[assembly: AssemblyTitle("sharp.json")]
|
||||
[assembly: AssemblyTitle("ln.json")]
|
||||
[assembly: AssemblyDescription("JSON Implementation")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
# sharp-json
|
||||
# sharp-json
|
||||
A lightweight JSON implementation for Mono/.NET
|
||||
|
||||
## Usage
|
||||
|
||||
Use the base type *sharp.json.JSON* to represent JSON variables.
|
||||
Use the base type *ln.json.JSON* to represent JSON variables.
|
||||
|
||||
import sharp.json;
|
||||
import ln.json;
|
||||
...
|
||||
JSON n = 123.45;
|
||||
JSON s = "Hello World!"
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
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,11 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace sharp.json.attributes
|
||||
{
|
||||
public class JSONField : Attribute
|
||||
{
|
||||
public string Alias { get; set; }
|
||||
public bool ConstructWithOwner { get; set; }
|
||||
public Type ConstructWithType { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,8 +1,7 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
|
||||
using sharp.json;
|
||||
using sharp.parser;
|
||||
using ln.json;
|
||||
|
||||
namespace json.test
|
||||
{
|
||||
|
@ -12,32 +11,32 @@ namespace json.test
|
|||
"\"I am a string\"",
|
||||
"{ \"me\" : \"is a string too\"}",
|
||||
"[ \"this\", \"is\", \"an\", \"array\" ]"
|
||||
|
||||
};
|
||||
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
JSONObject json = new JSONObject()
|
||||
.Add("version", new JSONNumber(123.456))
|
||||
.Add("text", new JSONString("Ich bin ein Text! Lächerlich, oder?"))
|
||||
.Add("Obst",new JSONArray()
|
||||
.Add(new JSONString("Apfel"))
|
||||
.Add(new JSONString("Birne"))
|
||||
.Add(new JSONString("Zwetschge"))
|
||||
.Add(JSONNull.Instance)
|
||||
.Add(JSONTrue.Instance)
|
||||
.Add(JSONFalse.Instance)
|
||||
)
|
||||
;
|
||||
|
||||
JSON json;
|
||||
JSONParser jsonparser = new JSONParser();
|
||||
Console.WriteLine(json.ToString());
|
||||
|
||||
json = jsonparser.Parse("4.9125E-05");
|
||||
Console.WriteLine(json.ToString());
|
||||
JSONValue json2 = JSONParser.Parse(json.ToString());
|
||||
Console.WriteLine(json2.ToString());
|
||||
|
||||
//Console.WriteLine("JSON test Patterns:");
|
||||
//Console.WriteLine();
|
||||
|
||||
//foreach (string src in sources){
|
||||
// json = jsonparser.Parse(src);
|
||||
// Console.WriteLine("NEW PARSER: {0}",json.ToString());
|
||||
//}
|
||||
|
||||
//json = jsonparser.Parse(File.ReadAllText("test.json"));
|
||||
//Console.WriteLine("");
|
||||
//Console.WriteLine("test.json file:");
|
||||
//Console.WriteLine("PARSED: {0}",json.ToString());
|
||||
|
||||
|
||||
}
|
||||
JSONValue value = JSONParser.Parse(File.ReadAllText("test.json"));
|
||||
Console.WriteLine("");
|
||||
Console.WriteLine("test.json file:");
|
||||
Console.WriteLine("PARSED: {0}",value.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
|
@ -34,13 +34,9 @@
|
|||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\sharp.json.csproj">
|
||||
<ProjectReference Include="..\ln.json.csproj">
|
||||
<Project>{D9342117-3249-4D8B-87C9-51A50676B158}</Project>
|
||||
<Name>sharp.json</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\sharp-parser\sharp.parser.csproj">
|
||||
<Project>{32267133-ADB7-4A85-8CF1-03CBDF53715C}</Project>
|
||||
<Name>sharp.parser</Name>
|
||||
<Name>ln.json</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{D9342117-3249-4D8B-87C9-51A50676B158}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<RootNamespace>sharp.json</RootNamespace>
|
||||
<AssemblyName>sharp.json</AssemblyName>
|
||||
<RootNamespace>ln.json</RootNamespace>
|
||||
<AssemblyName>ln.json</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
|
@ -31,54 +31,26 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="JSON.cs" />
|
||||
<Compile Include="ByteParser.cs" />
|
||||
<Compile Include="JSONSpecial.cs" />
|
||||
<Compile Include="JSONObject.cs" />
|
||||
<Compile Include="JSONArray.cs" />
|
||||
<Compile Include="JSONString.cs" />
|
||||
<Compile Include="JSONTypes.cs" />
|
||||
<Compile Include="JSONNumber.cs" />
|
||||
<Compile Include="JSONWebRequest.cs" />
|
||||
<Compile Include="JSONSerializer.cs" />
|
||||
<Compile Include="JSONValue.cs" />
|
||||
<Compile Include="JSONParser.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" />
|
||||
<Compile Include="simple\KeyValue.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\sharp-extensions\sharp.extensions.csproj">
|
||||
<Project>{97CA3CA9-98B3-4492-B072-D7A5995B68E9}</Project>
|
||||
<Name>sharp.extensions</Name>
|
||||
<ProjectReference Include="ln.types\ln.types.csproj">
|
||||
<Project>{8D9AB9A5-E513-4BA7-A450-534F6456BF28}</Project>
|
||||
<Name>ln.types</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\sharp-webclient\sharp.webclient.csproj">
|
||||
<Project>{01E98E3B-9462-4CF1-8421-4789763FBAA1}</Project>
|
||||
<Name>sharp.webclient</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\sharp-parser\sharp.parser.csproj">
|
||||
<Project>{32267133-ADB7-4A85-8CF1-03CBDF53715C}</Project>
|
||||
<Name>sharp.parser</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\sharp-contracts\sharp.contracts.csproj">
|
||||
<Project>{56733EC1-7D97-48D0-AA4C-98EA624A5A21}</Project>
|
||||
<Name>sharp.contracts</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="network\" />
|
||||
<Folder Include="attributes\" />
|
||||
<Folder Include="simple\" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<ProjectExtensions>
|
||||
<MonoDevelop>
|
||||
<Properties>
|
||||
<Policies>
|
||||
<DotNetNamingPolicy DirectoryNamespaceAssociation="PrefixedHierarchical" ResourceNamePolicy="FileFormatDefault" />
|
||||
<DotNetNamingPolicy ResourceNamePolicy="FileFormatDefault" DirectoryNamespaceAssociation="PrefixedHierarchical" />
|
||||
</Policies>
|
||||
</Properties>
|
||||
</MonoDevelop>
|
|
@ -1,57 +0,0 @@
|
|||
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();
|
||||
}
|
||||
|
||||
public TcpClient TcpClient
|
||||
{
|
||||
get { return this.client; }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ln.json", "ln.json.csproj", "{D9342117-3249-4D8B-87C9-51A50676B158}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "json.test", "json.test\json.test.csproj", "{49FFBD9F-655E-4C74-A078-99B5E09059C6}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ln.types", "ln.types\ln.types.csproj", "{8D9AB9A5-E513-4BA7-A450-534F6456BF28}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ln.logging", "ln.logging\ln.logging.csproj", "{D471A566-9FB6-41B2-A777-3C32874ECD0E}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{D9342117-3249-4D8B-87C9-51A50676B158}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D9342117-3249-4D8B-87C9-51A50676B158}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D9342117-3249-4D8B-87C9-51A50676B158}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D9342117-3249-4D8B-87C9-51A50676B158}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{49FFBD9F-655E-4C74-A078-99B5E09059C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{49FFBD9F-655E-4C74-A078-99B5E09059C6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{49FFBD9F-655E-4C74-A078-99B5E09059C6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{49FFBD9F-655E-4C74-A078-99B5E09059C6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8D9AB9A5-E513-4BA7-A450-534F6456BF28}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8D9AB9A5-E513-4BA7-A450-534F6456BF28}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8D9AB9A5-E513-4BA7-A450-534F6456BF28}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8D9AB9A5-E513-4BA7-A450-534F6456BF28}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D471A566-9FB6-41B2-A777-3C32874ECD0E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D471A566-9FB6-41B2-A777-3C32874ECD0E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D471A566-9FB6-41B2-A777-3C32874ECD0E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D471A566-9FB6-41B2-A777-3C32874ECD0E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
|
@ -1,20 +0,0 @@
|
|||
using System;
|
||||
namespace sharp.json.simple
|
||||
{
|
||||
public class KeyValue
|
||||
{
|
||||
public String Key;
|
||||
public String Value;
|
||||
|
||||
private KeyValue()
|
||||
{
|
||||
}
|
||||
|
||||
public KeyValue(string key,string value = "")
|
||||
{
|
||||
Key = key;
|
||||
Value = value;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue