marcoslopezc / lightjson Goto Github PK
View Code? Open in Web Editor NEWA simple JSON library for C#.
License: MIT License
A simple JSON library for C#.
License: MIT License
Changing the implementation of JsonValue will allow it to be compiled in .NET 3.5.
This project is currently targeting .NET Standard 2.1, which makes it unusable in any application targeting .NET Framework. I request a decrease in the target framework to .NET Standard 2.0 instead, to make it usable in more applications.
Add an interface (IJsonValue) so that all objects that represent a JSON value share a consistent interface.
Methods inside JsonReader are not suppose to access the reader directly. Instead, they are suppose to use the Read and Peek methods. However, this is error-prone. Instead, this behavior should be encapsulated into its own class.
The following both return true, but should not:
JsonValue.Null.Equals(1)
JsonValue.Null.Equals(new Exception())
π Originally found in DotNetAnalyzers/StyleCopAnalyzers#2406
Hi @MarcosLopezC,
After running into a variety of problems shipping a single binary that worked across numerous runtime environments (including .NET Core scenarios), the StyleCop Analyzers project is now looking at switching to an embedded copy of LightJson rather than depending on Json.NET. However, since this change is targeting a stable release branch, it was essential for us to not break existing users who could be relying on certain aspects of the relaxed syntax allowed by Json.NET, specifically:
Since we took the time to implement this required functionality for LightJson, I wanted to make you aware of the work in case you were interested in bringing it back into the core library. π
Code:
new JsonArray(default(JsonValue[]));
// Or equivalently:
new JsonArray((JsonValue[])null);
Expected exception: ArgumentNullException
, with paramName
set to values
Actual exception: NullReferenceException
π Originally found in DotNetAnalyzers/StyleCopAnalyzers#2406.
Examples of numbers which fail:
JsonValue.Parse("1")
JsonValue.Parse("1.0")
π Originally found in DotNetAnalyzers/StyleCopAnalyzers#2406
JsonObject currently performs two Dictionary when retrieving a value. This should be change so that only one lookup is needed.
You can use unchecked((int)value)
to ensure this exception is not thrown even in builds that use checked arithmetic, making the exception handler unreachable.
π Originally found in DotNetAnalyzers/StyleCopAnalyzers#2406
The key of a Json Object can be null. This behavior is not consistent with the JSON specifications.
var obj = JsonValue.Parse("[1,2]");
var writer = new JsonWriter(pretty: true) { IndentString = " " };
writer.Serialize(obj);
Expected:
[
1,
2
]
Actual:
[
1 ,
2
]
π Originally found in DotNetAnalyzers/StyleCopAnalyzers#2406.
π Originally found in DotNetAnalyzers/StyleCopAnalyzers#2406
Write a wiki page describing how to integrate and use LightJson.
Add methods to JsonValue such as ToBoolean, ToInt, ToNumber, ToObject, etc. These method will be used for non-strict conversions. The casting operators will be used for strict conversion.
Add Clone
method to JsonValue
, JsonObject
, and JsonArray
to allow for deep and shallow copies of Json values.
Instead of using Serialize to create a JSON string, use ToString method. That way the library can work in conjunction with other frameworks such as MVC.
Can you implement the following complex JSON formatsοΌ
{
"name": "Materials",
"version": "1.0",
"scene": {
"SceneUnit": 8215,
"YIsUp": 0
},
"materials": {
"0": {
"version": 2,
"userassets": [
"0"
],
"materials": {
"0": {
"tag": "",
"definition": "XXXX",
"properties": {
"integers": {
"mode": 4
},
"booleans": {
"generic_bump_is_normal": false,
"generic_is_metal": false,
"generic_backface_cull": false
},
"scalars": {
"generic_reflectivity_at_0deg": {
"values": [
0.2
]
},
"generic_glossiness": {
"values": [
0.0
]
}
},
"colors": {
"generic_diffuse": {
"values": [
{
"r": 1.0,
"g": 1.0,
"b": 1.0
}
]
},
"generic_specular": {
"values": [
{
"r": 0.2,
"g": 0.2,
"b": 0.2
}
]
}
}
},
"transparent": false,
"textures": {
"generic_diffuse": {
"connections": [
"1_generic_diffuse"
]
}
}
},
"1_generic_diffuse": {
"tag": "",
"definition": "UnifiedBitmap",
"properties": {
"uris": {
"unifiedbitmap_Bitmap": {
"values": [
"xxxxx"
]
}
},
"booleans": {
"unifiedbitmap_Invert": false,
"texture_URepeat": true,
"texture_VRepeat": true
},
"scalars": {
"texture_UScale": {
"units": "",
"values": [
0.0625
]
},
"texture_VScale": {
"units": "",
"values": [
0.0625
]
},
"texture_UOffset": {
"units": "",
"values": [
0.0
]
},
"texture_VOffset": {
"units": "",
"values": [
0.0
]
},
"texture_WAngle": {
"units": "",
"values": [
0.0
]
}
},
"integers": {
"texture_MapChannel": 1
}
}
}
}
},
"1": {
"version": 2,
"userassets": [
"0"
],
"materials": {
"0": {
"tag": "",
"definition": "SimplePhong",
"properties": {
"integers": {
"mode": 4
},
"booleans": {
"generic_bump_is_normal": false,
"generic_is_metal": false,
"generic_backface_cull": false
},
"scalars": {
"generic_glossiness": {
"values": [
64.0
]
}
},
"colors": {
"generic_diffuse": {
"values": [
{
"r": 0.49803921568627452,
"g": 0.49803921568627452,
"b": 0.49803921568627452
}
]
}
}
},
"transparent": false,
"textures": {}
}
}
}
}
}
If an object is used more than once, it triggers the CircularReferenceException, which is not necesarily correct.
JsonValue.Parse
will fail to parse the following:
{
"x": "value",
"value": "anything"
}
On a related note, the exception thrown for cases where the keys do collide is currently incorrect.
π Both issues above originally found in DotNetAnalyzers/StyleCopAnalyzers#2406
Currently, due to roslyn limitations, it's rather cumbersome to use Json libraries in source generators.
One approach, taken by https://github.com/DotNetAnalyzers/StyleCopAnalyzers was to copy over the code, and maintain it.
But it would be extremely useful to, instead, either have the source code embedded in the current package, or release a dedicated source code package.
As an example, scriban, already does that: https://github.com/scriban/scriban#source-embedding
I think if that was implemented, it would make it a very nice package to use in source generators.
Right now a JsonValue
can sometimes produce different JSON strings when serialized. This caused by the way the JsonObject
is serialized. By serializing the items within a JsonObject
is alphabetical order, we can be sure that we'll always produce the same JSON string for any given JsonValue
.
Add the method AddIfNotNull
to JsonObject
and JsonValue
. This method will add an item to its collection if the value is not null.
JsonReader.cs
private void ReadHexNum(StringBuilder builder)
{
while (this.scanner.CanRead && char.IsLetterOrDigit(this.scanner.Peek()))
{
builder.Append(this.scanner.Read());
}
}
private JsonValue ReadNumber()
{
....
if (this.scanner.CanRead && char.ToLowerInvariant(this.scanner.Peek()) == 'e')
{
...
}
if (this.scanner.CanRead && char.ToLowerInvariant(this.scanner.Peek()) == 'x')
{
char ch = this.scanner.Read();
builder.Clear();
ReadHexNum(builder);
if (8 >= builder.Length)
{
return Convert.ToUInt32(builder.ToString(), 16);
}
else if (16 >= builder.Length)
{
return Convert.ToUInt64(builder.ToString(), 16);
}
else // Convert to JsonArray? or not support?
{
//JsonArray ja = new JsonArray();
}
}
...
}
As far as I have understood, the textual representation of JSON numbers is not supposed to be affected by the current culture. For example it should always use a decimal period, even if the current culture uses decimal comma instead. LightJson does not seem to behave that way, due to the use of versions of ToString() and TryParse() which uses the current culture.
Some examples of the current behaviour, with culture "sv-SE":
new JsonValue("1.0").AsNumber
returns 0
new JsonValue(0.5).AsString
returns "0,5"
The following pull request changed that in the version of LightJson embedded in StyleCop.Analysers: DotNetAnalyzers/StyleCopAnalyzers#2442
The code might still not comply with the specification in http://json.org completely, but it can at least serve as a starting point if you would like to make LightJson more standards compliant.
In LightJson v0.2.1, string comparisons may fail if similar strings are in store in distinct string objects.
Code:
JsonValue.Parse("trUe");
Expected result: Error at line 0, column 2
Actual result: Error at line 0, column 3
Cause: TextScanner.Assert
calls TextScanner.Read
before validating the character, which causes the position to move forward by one. The current position needs to be stored in a local variable before calling Read
so it can be used for positioning in the event of an error.
π This was originally found in DotNetAnalyzers/StyleCopAnalyzers#2406.
Add a prototype feature to JsonObject.
Comparisons where a JsonValue
is on the left side of the equality operator causes the right value to be cast into a JsonValue
.
Add a method to JsonObject that allows keys to be renamed easily.
From the official JSON specification, section 9 (emphasis mine):
A string is a sequence of Unicode code points wrapped with quotation marks (U+0022). All code points may be placed within the quotation marks except for the code points that must be escaped: quotation mark (U+0022), reverse solidus (U+005C), and the control characters U+0000 to U+001F. There are two-character escape sequence representations of some characters.
JsonReader
checks for invalid control characters using char.IsControl()
, and from its documentation:
The Unicode standard assigns code points from \U0000 to \U001F, \U007F, and from \U0080 to \U009F to control characters.
In other words, there is a range of characters which are designated Unicode control characters (and thus return a positive result from char.IsControl()
) which are not deemed control characters according to the JSON standard. These characters will therefore not be escaped by many JSON serializers, which may cause an invalid JsonParseException
to be thrown when the JSON contains them.
Of course this is all very unlikely, and of course therefore it just happened to me while consuming a JSON API and I spent the last few hours debugging the problem (turns out, \u007f
doesn't quite show up in string output!).
EDIT: From the top of my head, as a suggested fix, I think replacing char.IsControl(c)
with c <= '\u001f'
should do the trick.
Implicit conversion operators should not throw exceptions during normal operations.
Make the constructors for JsonObject and JsonArray accept a string representing a json message to be deserialized.
Add explicit conversions operators to JsonValue
. These will throw exceptions if the underlying value is not of the exact type to which it is being converted.
When the old and new keys are the same, JsonObject.Rename
will remove the key rather than return without making changes.
var obj = new JsonObject { ["x"] = "value" };
obj.Rename("x", "x");
Assert.True(obj.ContainsKey("x")); // This currently fails
π This was originally found in DotNetAnalyzers/StyleCopAnalyzers#2406.
JsonReader
and JsonWriter
have too many responsibilities. Their task should be split into two new different object: JsonParser
and JsonSerializer
. This would result in JsonReader
and JsonWriter
being more generic; which would make then suitable to be used by other classes to do quick JSON reading or writing.
I noticed during work on DotNetAnalyzers/StyleCopAnalyzers#2406 that the following two items are not used:
JsonWriter.IsValidNumber
JsonSerializationException.InvalidNumber
JsonWriter should be able to serialize any kinds of JSON value, not just objects and arrays.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.