11 Commits
1_0 ... 1_1_1

7 changed files with 233 additions and 128 deletions

1
.gitignore vendored
View File

@@ -27,3 +27,4 @@ obj/
_ReSharper*/ _ReSharper*/
*.userprefs *.userprefs
*.nupkg *.nupkg
/.vs/*

View File

@@ -96,7 +96,7 @@ namespace VAR.Json.Tests
} }
if (obj != null && (obj is Exception) == false) if (obj != null && (obj is Exception) == false)
{ {
JsonWriter writter = new JsonWriter(true); JsonWriter writter = new JsonWriter(new JsonWriterConfiguration(indent: true));
Console.Out.WriteLine("Parsed:\n{0}", writter.Write(obj)); Console.Out.WriteLine("Parsed:\n{0}", writter.Write(obj));
Console.Out.WriteLine("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); Console.Out.WriteLine("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
} }

View File

@@ -15,7 +15,7 @@ namespace VAR.Json
private ParserContext _ctx; private ParserContext _ctx;
private bool _tainted = false; private bool _tainted = false;
private List<Type> _knownTypes = new List<Type>(); private readonly List<Type> _knownTypes = new List<Type>();
#endregion Declarations #endregion Declarations
@@ -35,7 +35,7 @@ namespace VAR.Json
#region Private methods #region Private methods
private static Dictionary<Type, PropertyInfo[]> _dictProperties = new Dictionary<Type, PropertyInfo[]>(); private static readonly Dictionary<Type, PropertyInfo[]> _dictProperties = new Dictionary<Type, PropertyInfo[]>();
private PropertyInfo[] Type_GetProperties(Type type) private PropertyInfo[] Type_GetProperties(Type type)
{ {
@@ -497,7 +497,7 @@ namespace VAR.Json
else if (c == ',') else if (c == ',')
{ {
_ctx.Next(); _ctx.Next();
c = _ctx.SkipWhite(); _ctx.SkipWhite();
expectedKey = true; expectedKey = true;
expectedValue = false; expectedValue = false;
} }
@@ -517,7 +517,7 @@ namespace VAR.Json
if (expectedKey != false) if (expectedKey != false)
{ {
attributeName = ParseString(true); attributeName = ParseString(true);
c = _ctx.SkipWhite(); _ctx.SkipWhite();
expectedKey = false; expectedKey = false;
expectedValue = true; expectedValue = true;
} }
@@ -538,8 +538,8 @@ namespace VAR.Json
private object ParseValue(int recusiveCount = 1) private object ParseValue(int recusiveCount = 1)
{ {
object token = null;
char c = _ctx.SkipWhite(); char c = _ctx.SkipWhite();
object token;
switch (c) switch (c)
{ {
case '"': case '"':
@@ -597,28 +597,6 @@ namespace VAR.Json
return token; return token;
} }
private string CleanIdentifier(string input)
{
int i;
char c;
i = input.Length - 1;
if (i < 0)
{
return input;
}
c = input[i];
while (char.IsLetter(c) || char.IsDigit(c) || c == '_')
{
i--;
if (i < 0)
{
break;
}
c = input[i];
}
return input.Substring(i + 1);
}
#endregion Private methods #endregion Private methods
#region Public methods #region Public methods
@@ -648,6 +626,19 @@ namespace VAR.Json
return obj; return obj;
} }
private static JsonParser _currentInstance = null;
public static object ParseText(string text, params Type[] knownTypes)
{
if (_currentInstance == null)
{
_currentInstance = new JsonParser();
}
_currentInstance.KnownTypes.Clear();
_currentInstance.KnownTypes.AddRange(knownTypes);
return _currentInstance.Parse(text);
}
#endregion Public methods #endregion Public methods
} }
} }

View File

@@ -1,39 +1,79 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Reflection; using System.Reflection;
using System.Text;
namespace VAR.Json namespace VAR.Json
{ {
public class JsonWriterConfiguration
{
private bool _indent;
public bool Indent { get { return _indent; } }
private bool _useTabForIndent;
public bool UseTabForIndent { get { return _useTabForIndent; } }
private int _indentChars;
public int IndentChars { get { return _indentChars; } }
private int _indentThresold;
public int IndentThresold { get { return _indentThresold; } }
public JsonWriterConfiguration(
bool indent = false,
bool useTabForIndent = false,
int indentChars = 4,
int indentThresold = 3)
{
_indent = indent;
_useTabForIndent = useTabForIndent;
_indentChars = indentChars;
_indentThresold = indentThresold;
}
public bool Equals(JsonWriterConfiguration other)
{
return
other.Indent == Indent &&
other.UseTabForIndent == UseTabForIndent &&
other.IndentChars == IndentChars &&
other.IndentThresold == IndentThresold &&
true;
}
public override bool Equals(object other)
{
if (other is JsonWriterConfiguration)
{
return Equals(other as JsonWriterConfiguration);
}
return false;
}
public override int GetHashCode()
{
return _indent.GetHashCode() ^ _useTabForIndent.GetHashCode() ^ _indentChars.GetHashCode() ^ _indentThresold.GetHashCode();
}
}
public class JsonWriter public class JsonWriter
{ {
#region Declarations #region Declarations
private bool _indent = false; private JsonWriterConfiguration _config = null;
private bool _useTabForIndent = false;
private int _indentChars = 4;
private int _indentThresold = 3;
#endregion Declarations #endregion Declarations
#region Creator #region Creator
public JsonWriter() public JsonWriter(JsonWriterConfiguration config = null)
{ {
_config = config;
if (_config == null)
{
_config = new JsonWriterConfiguration();
} }
public JsonWriter(int indentChars)
{
_indent = true;
_indentChars = indentChars;
_useTabForIndent = false;
}
public JsonWriter(bool useTabForIndent)
{
_indent = true;
_useTabForIndent = useTabForIndent;
} }
#endregion Creator #endregion Creator
@@ -61,52 +101,52 @@ namespace VAR.Json
return false; return false;
} }
private void WriteIndent(StringBuilder sbOutput, int level) private void WriteIndent(TextWriter textWriter, int level)
{ {
if (!_indent) if (!_config.Indent)
{ {
return; return;
} }
sbOutput.Append('\n'); textWriter.Write('\n');
if (_useTabForIndent) if (_config.UseTabForIndent)
{ {
for (int i = 0; i < level; i++) { sbOutput.Append('\t'); } for (int i = 0; i < level; i++) { textWriter.Write('\t'); }
} }
else else
{ {
int n = level * _indentChars; int n = level * _config.IndentChars;
for (int i = 0; i < n; i++) { sbOutput.Append(' '); } for (int i = 0; i < n; i++) { textWriter.Write(' '); }
} }
} }
private void WriteString(StringBuilder sbOutput, string str) private void WriteString(TextWriter textWriter, string str)
{ {
sbOutput.Append('"'); textWriter.Write('"');
char c; char c;
int n = str.Length; int n = str.Length;
for (int i = 0; i < n; i++) for (int i = 0; i < n; i++)
{ {
c = str[i]; c = str[i];
if (c == '"') { sbOutput.Append("\\\""); } if (c == '"') { textWriter.Write("\\\""); }
else if (c == '\\') { sbOutput.Append("\\\\"); } else if (c == '\\') { textWriter.Write("\\\\"); }
else if (c == '/') { sbOutput.Append("\\/"); } else if (c == '/') { textWriter.Write("\\/"); }
else if (c == '\b') { sbOutput.Append("\\b"); } else if (c == '\b') { textWriter.Write("\\b"); }
else if (c == '\f') { sbOutput.Append("\\f"); } else if (c == '\f') { textWriter.Write("\\f"); }
else if (c == '\n') { sbOutput.Append("\\n"); } else if (c == '\n') { textWriter.Write("\\n"); }
else if (c == '\r') { sbOutput.Append("\\r"); } else if (c == '\r') { textWriter.Write("\\r"); }
else if (c == '\t') { sbOutput.Append("\\t"); } else if (c == '\t') { textWriter.Write("\\t"); }
else if (c < 32 || c >= 127) { sbOutput.AppendFormat("\\u{0:X04}", (int)c); } else if (c < 32 || c >= 127) { textWriter.Write("\\u{0:X04}", (int)c); }
else { sbOutput.Append(c); } else { textWriter.Write(c); }
} }
sbOutput.Append('"'); textWriter.Write('"');
} }
private void WriteValue(StringBuilder sbOutput, object obj, List<object> parentLevels, bool useReflection) private void WriteValue(TextWriter textWriter, object obj, List<object> parentLevels, bool useReflection)
{ {
if (obj == null || obj is DBNull) if (obj == null || obj is DBNull)
{ {
// NULL // NULL
sbOutput.Append("null"); textWriter.Write("null");
} }
else if ( else if (
(obj is float) || (obj is float) ||
@@ -117,50 +157,50 @@ namespace VAR.Json
false) false)
{ {
// Numbers // Numbers
sbOutput.Append(obj.ToString()); textWriter.Write(obj.ToString());
} }
else if (obj is string) else if (obj is string)
{ {
// Strings // Strings
WriteString(sbOutput, (string)obj); WriteString(textWriter, (string)obj);
} }
else if (obj is bool) else if (obj is bool)
{ {
// Booleans // Booleans
sbOutput.Append(((bool)obj) ? "true" : "false"); textWriter.Write(((bool)obj) ? "true" : "false");
} }
else if (obj is DateTime) else if (obj is DateTime)
{ {
// DateTime // DateTime
sbOutput.Append('"'); textWriter.Write('"');
sbOutput.Append(((DateTime)obj).ToString("yyyy-MM-ddTHH:mm:ssZ")); textWriter.Write(((DateTime)obj).ToString("yyyy-MM-ddTHH:mm:ssZ"));
sbOutput.Append('"'); textWriter.Write('"');
} }
else if (obj is IDictionary) else if (obj is IDictionary)
{ {
// Objects // Objects
WriteObject(sbOutput, obj, parentLevels); WriteObject(textWriter, obj, parentLevels);
} }
else if (obj is IEnumerable) else if (obj is IEnumerable)
{ {
// Array/List // Array/List
WriteList(sbOutput, obj, parentLevels); WriteList(textWriter, obj, parentLevels);
} }
else else
{ {
if (useReflection) if (useReflection)
{ {
// Reflected object // Reflected object
WriteReflectedObject(sbOutput, obj, parentLevels); WriteReflectedObject(textWriter, obj, parentLevels);
} }
else else
{ {
WriteString(sbOutput, Convert.ToString(obj)); WriteString(textWriter, Convert.ToString(obj));
} }
} }
} }
private void WriteList(StringBuilder sbOutput, object obj, List<object> parentLevels) private void WriteList(TextWriter textWriter, object obj, List<object> parentLevels)
{ {
IEnumerable list = (IEnumerable)obj; IEnumerable list = (IEnumerable)obj;
int n = 0; int n = 0;
@@ -179,40 +219,40 @@ namespace VAR.Json
// Empty // Empty
if (n == 0) if (n == 0)
{ {
sbOutput.Append("[ ]"); textWriter.Write("[ ]");
return; return;
} }
// Write array // Write array
bool first = true; bool first = true;
sbOutput.Append("[ "); textWriter.Write("[ ");
if (!isLeaf || n > _indentThresold) if (!isLeaf || n > _config.IndentThresold)
{ {
WriteIndent(sbOutput, parentLevels.Count + 1); WriteIndent(textWriter, parentLevels.Count + 1);
} }
foreach (object childObj in list) foreach (object childObj in list)
{ {
if (!first) if (!first)
{ {
sbOutput.Append(", "); textWriter.Write(", ");
if (!isLeaf || n > _indentThresold) if (!isLeaf || n > _config.IndentThresold)
{ {
WriteIndent(sbOutput, parentLevels.Count + 1); WriteIndent(textWriter, parentLevels.Count + 1);
} }
} }
first = false; first = false;
parentLevels.Add(obj); parentLevels.Add(obj);
WriteValue(sbOutput, childObj, parentLevels, true); WriteValue(textWriter, childObj, parentLevels, true);
parentLevels.Remove(obj); parentLevels.Remove(obj);
} }
if (!isLeaf || n > _indentThresold) if (!isLeaf || n > _config.IndentThresold)
{ {
WriteIndent(sbOutput, parentLevels.Count); WriteIndent(textWriter, parentLevels.Count);
} }
sbOutput.Append(" ]"); textWriter.Write(" ]");
} }
private void WriteObject(StringBuilder sbOutput, object obj, List<object> parentLevels) private void WriteObject(TextWriter textWriter, object obj, List<object> parentLevels)
{ {
IDictionary map = (IDictionary)obj; IDictionary map = (IDictionary)obj;
int n = map.Count; int n = map.Count;
@@ -220,7 +260,7 @@ namespace VAR.Json
// Empty // Empty
if (map.Count == 0) if (map.Count == 0)
{ {
sbOutput.Append("{ }"); textWriter.Write("{ }");
return; return;
} }
@@ -237,37 +277,37 @@ namespace VAR.Json
// Write object // Write object
bool first = true; bool first = true;
sbOutput.Append("{ "); textWriter.Write("{ ");
if (!isLeaf || n > _indentThresold) if (!isLeaf || n > _config.IndentThresold)
{ {
WriteIndent(sbOutput, parentLevels.Count + 1); WriteIndent(textWriter, parentLevels.Count + 1);
} }
foreach (object key in map.Keys) foreach (object key in map.Keys)
{ {
object value = map[key]; object value = map[key];
if (!first) if (!first)
{ {
sbOutput.Append(", "); textWriter.Write(", ");
if (!isLeaf || n > _indentThresold) if (!isLeaf || n > _config.IndentThresold)
{ {
WriteIndent(sbOutput, parentLevels.Count + 1); WriteIndent(textWriter, parentLevels.Count + 1);
} }
} }
first = false; first = false;
WriteString(sbOutput, Convert.ToString(key)); WriteString(textWriter, Convert.ToString(key));
sbOutput.Append(": "); textWriter.Write(": ");
parentLevels.Add(obj); parentLevels.Add(obj);
WriteValue(sbOutput, value, parentLevels, true); WriteValue(textWriter, value, parentLevels, true);
parentLevels.Remove(obj); parentLevels.Remove(obj);
} }
if (!isLeaf || n > _indentThresold) if (!isLeaf || n > _config.IndentThresold)
{ {
WriteIndent(sbOutput, parentLevels.Count); WriteIndent(textWriter, parentLevels.Count);
} }
sbOutput.Append(" }"); textWriter.Write(" }");
} }
private void WriteReflectedObject(StringBuilder sbOutput, object obj, List<object> parentLevels) private void WriteReflectedObject(TextWriter textWriter, object obj, List<object> parentLevels)
{ {
Type type = obj.GetType(); Type type = obj.GetType();
PropertyInfo[] rawProperties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance); PropertyInfo[] rawProperties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
@@ -283,7 +323,7 @@ namespace VAR.Json
// Empty // Empty
if (n == 0) if (n == 0)
{ {
sbOutput.Append("{ }"); textWriter.Write("{ }");
return; return;
} }
@@ -301,10 +341,10 @@ namespace VAR.Json
// Write object // Write object
bool first = true; bool first = true;
sbOutput.Append("{ "); textWriter.Write("{ ");
if (!isLeaf || n > _indentThresold) if (!isLeaf || n > _config.IndentThresold)
{ {
WriteIndent(sbOutput, parentLevels.Count + 1); WriteIndent(textWriter, parentLevels.Count + 1);
} }
foreach (PropertyInfo property in properties) foreach (PropertyInfo property in properties)
{ {
@@ -317,42 +357,106 @@ namespace VAR.Json
} }
if (!first) if (!first)
{ {
sbOutput.Append(", "); textWriter.Write(", ");
if (!isLeaf || n > _indentThresold) if (!isLeaf || n > _config.IndentThresold)
{ {
WriteIndent(sbOutput, parentLevels.Count + 1); WriteIndent(textWriter, parentLevels.Count + 1);
} }
} }
first = false; first = false;
WriteString(sbOutput, property.Name); WriteString(textWriter, property.Name);
sbOutput.Append(": "); textWriter.Write(": ");
parentLevels.Add(obj); parentLevels.Add(obj);
if (value != obj && parentLevels.Contains(value) == false) if (value != obj && parentLevels.Contains(value) == false)
{ {
WriteValue(sbOutput, value, parentLevels, false); WriteValue(textWriter, value, parentLevels, false);
} }
else else
{ {
WriteValue(sbOutput, null, parentLevels, false); WriteValue(textWriter, null, parentLevels, false);
} }
parentLevels.Remove(obj); parentLevels.Remove(obj);
} }
if (!isLeaf || n > _indentThresold) if (!isLeaf || n > _config.IndentThresold)
{ {
WriteIndent(sbOutput, parentLevels.Count); WriteIndent(textWriter, parentLevels.Count);
} }
sbOutput.Append(" }"); textWriter.Write(" }");
} }
#endregion Private methods #endregion Private methods
#region Public methods #region Public methods
public TextWriter Write(object obj, TextWriter textWriter)
{
if (textWriter == null)
{
textWriter = new StringWriter();
}
WriteValue(textWriter, obj, new List<object>(), true);
return textWriter;
}
public string Write(object obj) public string Write(object obj)
{ {
StringBuilder sbOutput = new StringBuilder(); StringWriter textWriter = new StringWriter();
WriteValue(sbOutput, obj, new List<object>(), true); WriteValue(textWriter, obj, new List<object>(), true);
return sbOutput.ToString(); return textWriter.ToString();
}
private static Dictionary<JsonWriterConfiguration, JsonWriter> _dictInstances = new Dictionary<JsonWriterConfiguration, JsonWriter>();
public static string WriteObject(object obj,
JsonWriterConfiguration config = null,
bool indent = false,
bool useTabForIndent = false,
int indentChars = 4,
int indentThresold = 3)
{
JsonWriter jsonWriter = null;
if (config != null)
{
if (_dictInstances.ContainsKey(config) == false)
{
jsonWriter = new JsonWriter(config);
_dictInstances.Add(config, jsonWriter);
}
else
{
jsonWriter = _dictInstances[config];
}
return jsonWriter.Write(obj);
}
foreach (KeyValuePair<JsonWriterConfiguration, JsonWriter> pair in _dictInstances)
{
if (
pair.Key.Indent == indent &&
pair.Key.UseTabForIndent == useTabForIndent &&
pair.Key.IndentChars == indentChars &&
pair.Key.IndentThresold == indentThresold &&
true)
{
jsonWriter = pair.Value;
break;
}
}
if (jsonWriter != null)
{
return jsonWriter.Write(obj);
}
JsonWriterConfiguration jsonWriterConfiguration = new JsonWriterConfiguration(
indent: indent,
useTabForIndent: useTabForIndent,
indentChars: indentChars,
indentThresold: indentThresold);
jsonWriter = new JsonWriter(jsonWriterConfiguration);
_dictInstances.Add(jsonWriterConfiguration, jsonWriter);
return jsonWriter.Write(obj);
} }
#endregion Public methods #endregion Public methods

View File

@@ -6,7 +6,7 @@ namespace VAR.Json
{ {
public class ObjectActivator public class ObjectActivator
{ {
private static Dictionary<Type, Func<object>> _creators = new Dictionary<Type, Func<object>>(); private static readonly Dictionary<Type, Func<object>> _creators = new Dictionary<Type, Func<object>>();
public static Func<object> GetLambdaNew(Type type) public static Func<object> GetLambdaNew(Type type)
{ {
@@ -17,14 +17,19 @@ namespace VAR.Json
lock (_creators) lock (_creators)
{ {
if (_creators.ContainsKey(type))
{
return _creators[type];
}
NewExpression newExp = Expression.New(type); NewExpression newExp = Expression.New(type);
LambdaExpression lambda = Expression.Lambda(typeof(Func<object>), newExp); LambdaExpression lambda = Expression.Lambda(typeof(Func<object>), newExp);
Func<object> compiledLambdaNew = (Func<object>)lambda.Compile(); Func<object> compiledLambdaNew = (Func<object>)lambda.Compile();
_creators.Add(type, compiledLambdaNew); _creators.Add(type, compiledLambdaNew);
}
return _creators[type]; return _creators[type];
} }
}
public static object CreateInstance(Type type) public static object CreateInstance(Type type)
{ {

View File

@@ -11,4 +11,4 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
[assembly: ComVisible(false)] [assembly: ComVisible(false)]
[assembly: Guid("28b3f937-145c-4fd4-a75b-a25ea4cc0428")] [assembly: Guid("28b3f937-145c-4fd4-a75b-a25ea4cc0428")]
[assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.1.1.*")]

View File

@@ -21,6 +21,7 @@
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion> <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<LangVersion>6</LangVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release .Net 4.6.1|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release .Net 4.6.1|AnyCPU' ">
<DebugType>pdbonly</DebugType> <DebugType>pdbonly</DebugType>
@@ -30,6 +31,7 @@
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion> <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<LangVersion>6</LangVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug .Net 3.5|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug .Net 3.5|AnyCPU' ">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
@@ -40,6 +42,7 @@
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion> <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<LangVersion>6</LangVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release .Net 3.5|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release .Net 3.5|AnyCPU' ">
<DebugType>pdbonly</DebugType> <DebugType>pdbonly</DebugType>
@@ -49,6 +52,7 @@
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion> <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<LangVersion>6</LangVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="System" /> <Reference Include="System" />