Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for different naming styles, and options for circular reference handling #62

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 106 additions & 1 deletion UnitTests/Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1386,6 +1386,85 @@ public static void CircularReferences()
Assert.AreEqual(p.o2obj, p.child.child);
}


class Circular
{
public Guid Id;
public Circular Parent;
public Circular Child;

public Circular()
{
Id = Guid.NewGuid();
}

public static Circular Create()
{
var a = new Circular();
var b = new Circular() { Parent = a };
a.Child = b;
var c = new Circular() { Parent = b };
b.Child = c;
var d = new Circular() { Parent = c };
c.Child = d;
return a;
}

}

[Test]
public static void CircularReferencesThrows()
{
var obj = Circular.Create();

Assert.That(() =>
{
JSON.ToJSON(obj,
new JSONParameters()
{
SerializerMaxDepth = 2,
SerializerMaxDepthHandling = InvalidObjectActions.Throw,
InlineCircularReferences = true
});
},
Throws.TypeOf<Exception>());
}

[Test]
public static void CircularReferencesNull()
{
var obj = Circular.Create();

var s = JSON.ToJSON(obj,
new JSONParameters()
{
SerializeNullValues = false,
SerializerMaxDepth = 3,
SerializerMaxDepthHandling = InvalidObjectActions.InsertNull,
InlineCircularReferences = true
});
Console.WriteLine(JSON.Beautify(s));
StringAssert.Contains("null", s);
}

[Test]
public static void CircularReferencesEmpty()
{
var obj = Circular.Create();

var s = JSON.ToJSON(obj,
new JSONParameters()
{
SerializeNullValues = false,
SerializerMaxDepth = 4,
SerializerMaxDepthHandling = InvalidObjectActions.InsertEmpty,
InlineCircularReferences = true
});
Console.WriteLine(s);
Console.WriteLine(JSON.Beautify(s));
StringAssert.Contains("{}", s);
}

public class lol
{
public List<List<object>> r;
Expand Down Expand Up @@ -1625,14 +1704,40 @@ public static void lowercaseSerilaize()
r.Field1 = "dsasdF";
r.Field2 = 2312;
r.date = DateTime.Now;
var s = JSON.ToNiceJSON(r, new JSONParameters { SerializeToLowerCaseNames = true });
var s = JSON.ToNiceJSON(r, new JSONParameters { NamingStyle = NamingStyles.LowerCase });
Console.WriteLine(s);
var o = JSON.ToObject(s);
Assert.IsNotNull(o);
Assert.AreEqual("Hello", (o as Retclass).Name);
Assert.AreEqual(2312, (o as Retclass).Field2);
}

[Test]
public static void PropertyName_Normal()
{
var obj = new { NameProperty = "Test" };
var s = JSON.ToJSON(obj, new JSONParameters { NamingStyle = NamingStyles.Normal, EnableAnonymousTypes = true });
Console.WriteLine(s);
Assert.AreEqual("{\"NameProperty\":\"Test\"}", s);
}

[Test]
public static void PropertyName_LowerCase()
{
var obj = new { NameProperty = "Test" };
var s = JSON.ToJSON(obj, new JSONParameters { NamingStyle = NamingStyles.LowerCase, EnableAnonymousTypes = true });
Console.WriteLine(s);
Assert.AreEqual("{\"nameproperty\":\"Test\"}", s);
}

[Test]
public static void PropertyName_CamelCase()
{
var obj = new { NameProperty = "Test", CRC = "1234" };
var s = JSON.ToJSON(obj, new JSONParameters { NamingStyle = NamingStyles.CamelCase, EnableAnonymousTypes = true });
Console.WriteLine(s);
Assert.AreEqual("{\"nameProperty\":\"Test\",\"crc\":\"1234\"}", s);
}

public class nulltest
{
Expand Down
87 changes: 87 additions & 0 deletions fastJSON/JSON.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,40 @@ namespace fastJSON
{
public delegate string Serialize(object data);
public delegate object Deserialize(string data);
public delegate string TextHandler(string name);
public delegate void InvalidObjectHandler(object obj);

public enum NamingStyles
{
/// <summary>
/// Leave name as is
/// </summary>
Normal = 0,
/// <summary>
/// Transform to lower case
/// </summary>
LowerCase = 1,
/// <summary>
/// Transform to camel case (Lowers the first char)
/// </summary>
CamelCase = 2
}

public enum InvalidObjectActions
{
/// <summary>
/// Throws an exception
/// </summary>
Throw = 0,
/// <summary>
/// Inserts a "null"
/// </summary>
InsertNull = 1,
/// <summary>
/// Inserts an empty object "{}"
/// </summary>
InsertEmpty = 2
}

public sealed class JSONParameters
{
Expand Down Expand Up @@ -83,14 +117,23 @@ public sealed class JSONParameters
/// </summary>
public byte SerializerMaxDepth = 20;
/// <summary>
/// Default action for when the <see cref="SerializerMaxDepth"/> limit is hit.
/// </summary>
public InvalidObjectActions SerializerMaxDepthHandling = InvalidObjectActions.Throw;
/// <summary>
/// Inline circular or already seen objects instead of replacement with $i (default = False)
/// </summary>
public bool InlineCircularReferences = false;
/// <summary>
/// Save property/field names as lowercase (default = false)
/// </summary>
[Obsolete("Use the NamingStyle property instead")]
public bool SerializeToLowerCaseNames = false;
/// <summary>
/// Naming style for property/field name (default = normal, leave as is)
/// </summary>
public NamingStyles NamingStyle = NamingStyles.Normal;
/// <summary>
/// Formatter indent spaces (default = 3)
/// </summary>
public byte FormatterIndentSpaces = 3;
Expand Down Expand Up @@ -1208,4 +1251,48 @@ DataTable CreateDataTable(Dictionary<string, object> reader, Dictionary<string,
#endregion
}

internal class nameHandler
{
private readonly TextHandler _handle;

internal nameHandler(NamingStyles style)
{
switch (style)
{
case NamingStyles.LowerCase:
_handle = (s) => s.ToLower();
break;
case NamingStyles.CamelCase:
_handle = (s) =>
{
var chars = s.ToCharArray();
var isAllUpper = true;
for (var ci = 0; ci < chars.Length; ci++)
{
if (!Char.IsUpper(chars[ci]))
{
isAllUpper = false;
break;
}
}
if (isAllUpper)
return s.ToLower();
chars[0] = Char.ToLower(chars[0]);
return new string(chars);
};
break;
case NamingStyles.Normal:
default:
_handle = (s) => s;
break;
}
}

internal string Handle(string name)
{
return _handle(name);
}

}

}
Loading