Coder Social home page Coder Social logo

json's Introduction

Tiny Json

Build Status License NuGet

A really simple C# JSON parser in ~350 lines

  • Attempts to parse JSON files with minimal GC allocation
  • Nice and simple "[1,2,3]".FromJson<List<int>>() API
  • Classes and structs can be parsed too!
class Foo 
{ 
  public int Value;
}
"{\"Value\":10}".FromJson<Foo>()
  • Anonymous JSON is parsed into Dictionary<string,object> and List<object>
var test = "{\"Value\":10}".FromJson<object>();
int number = ((Dictionary<string,object>)test)["Value"];
  • No JIT Emit support to support AOT compilation on iOS
  • Attempts are made to NOT throw an exception if the JSON is corrupted or invalid: returns null instead.
  • Only public fields and property setters on classes/structs will be written to
  • You can optionally use [IgnoreDataMember] and [DataMember(Name="Foo")] to ignore vars and override the default name

Limitations:

  • No JIT Emit support to parse structures quickly
  • Limited to parsing <2GB JSON files (due to int.MaxValue)
  • Parsing of abstract classes or interfaces is NOT supported and will throw an exception.

Changelog

  • v1.1 Support added for Enums and fixed Unity compilation
  • v1.0 Initial Release

Example Usage

This example will write a list of ints to a File and read it back again:

using System;
using System.IO;
using System.Collections.Generic;

using TinyJson;

public static class JsonTest
{
  public static void Main(string[] args)
  {
    //Write a file
    List<int> values = new List<int> { 1, 2, 3, 4, 5, 6 };
    string json = values.ToJson();
    File.WriteAllText("test.json", json);
    
    //Read it back
    string fileJson = File.ReadAllText("test.json");
    List<int> fileValues = fileJson.FromJson<List<int>>();
  }
}

Save this as JsonTest.cs then compile and run with mcs JsonTest.cs && mono JsonTest.exe

Installation

Simply copy and paste the JSON Parser and/or the JSON Writer into your project. I also provide NuGet but I recommend the copy paste route ;)

json's People

Contributors

cnyarx avatar forestrf avatar gusarov avatar lhzcm avatar malmer avatar pracplayopen avatar sungiant avatar thegoldenmule avatar wassili-hense avatar yanpas avatar zanders3 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

json's Issues

Praise

Hi Alex,

Your JSON parser has saved my life.

I found it just minutes before embarking on doing the same myself and I am positive it would not have come out as beautiful as yours.

I am working within the limits of a quite crappy application that supposedly is extendable using C# but fails that claim on many counts. So neither of the common solutions for digesting JSON worked for me and the only way forward is straight non-library literally-put-stuff-here coding. Which you provided.

Thank you very, very much!

Your code worked almost out of the box. I did have to change the Stack<List> splitArrayPool to a List<List>. I blame the general crappiness of the environment I am stuck in on that, because it simply refused to provide a Stack no matter what I tried. And I feel sorry for the mutilation.

Have a good time!

Can't parse DateTime?

I am unable to parse this. Comes back as default DateTime.Min value.

String:
{"MachineID":"abc","LicenseKey":"def","AuthToken":"3926AB247AF62B3F750BE991963B887E37F1DD61","ExpirationDate":"01/01/2040","ServerValidationToken":"ghi","IsSuccess":true,"LicenseErrorMessage":null}

Class:

    internal class MyClass
    {
        public string MachineID { get; set; }
        public string LicenseKey { get; set; }
        public string AuthToken { get; set; }
        public DateTime ExpirationDate { get; set; } // Issue is here.
        public string ServerValidationToken { get; set; }
        public bool IsSuccess { get; set; }
        public string LicenseErrorMessage { get; set; }
    }

ParseAnonymousValue issue

I cannot understand that str.Replace("\\", string.Empty); at 283 line in JSONParser.cs

When I try to parse {"abc": "he\rllo"},I got {"abc": "herllo"}

How is System.Threading.Tasks used in JSONWriter?

This library works in Unity, with the exception of System.Threading.Tasks namespace, which is .NET 4 (while Unity is 3.5-ish). I commented it out, and Unity doesn't complain anymore, so I am wondering how it's used.

PS: I only use JSONParser at the moment, so it isn't a big deal to me, just wondering.

Fix: backslash is written incorrectly! (when Dictionary is being processed)

The writer generates something like:
{"ScanDictionaries":{"..\":"a","%cd%\..\":"b"}}
instead of
{"ScanDictionaries":{"..\\":"a","%cd%\\..\\":"b"}}

FIX:
In JSONWriter.cs
at line 126
change stringBuilder.Append((string)key); to
stringBuilder.Append(((string)key).Replace("\\", "\\\\"));

In JSONParser.cs
at line 243
change string keyValue = elems[i].Substring(1, elems[i].Length - 2); to
string keyValue = elems[i].Substring(1, elems[i].Length - 2).Replace("\\\\", "\\");

Note: I noticed this problem only in Dictionary writing, maybe there are other similar mistakes.
Also, I want to add that this solution could be wrong.

Technically valid JSON not parsed

Nothing in the JSON spec says you can't have duplicate keys. So e.g. I have come across JSON like this which made it through other JSON processors in the wild:

{
   "name": "Peter",
   "age": 31,
   "name": "Peter"
}

When using TinyJson.JSONParser.FromJson<Dictionary<string, object>> on the document above, it throws an error saying that the dictionary already contains a key of the same name.

This behaviour might be desirable in some circumstances, but I need to use it in a way which ensures it can cope with strange files like the one above. In the case shown, most processors just overwrite the first value of name with the subsequent one(s).

I'd say the code should default to allowing valid JSON and allow turning on of this "duplicate key handling by exception" behaviour via some sort of flag?

empty list '[]' is parsed to a list with null

when calling JSONParser.ParseAnonymousValue() with the string "[]" it returns a list with 1 null element.
This is because JSONParser.Split() always adds at the end the string in the stringBuilder, even if it is an empty string

JSONParser and JSONWriter issues when handle "\" and "\\"

line 128 of JSONWriter.cs
``str.Replace("\", string.Empty)should be:str.Replace("\\", """").Replace("\", string.Empty).Replace("""", "\");`

line 36 of JSONWriter.cs
stringBuilder.Append((string)item));
should be:
stringBuilder.Append(((string)item).Replace("\\", "\\\\"));

Test with json lib of python 2.7
import json json.loads('["foo\\bar"]') # wrong
[u'foo\x08ar']

json.loads(json.dumps(["foo\bar"])) # wrong
[u'foo\x08ar']

json.loads('["foo\\\\bar"]') # right
[u'foo\bar']

json.dumps(["foo\\bar"]) # right
'["foo\bar"]'

Issue serializing classes/structs with static variables of the same type

Trying to serialize this struct:

public struct Color {
  public byte R, G, B;
  public Color(byte r, byte g, byte b)
  {
    R = r;
    G = g;
    B = b;
  }
  public static Color Zero = new Color(0, 0, 0);
}

causes a stack overflow.

Initial issue was the byte types. After adding the byte types (along with all the missing numeric types for other classes that need it) it gets stuck at the static (goes into the static and then in the static it finds the static again and so on).
I've bypassed it for now by adding && !fieldInfos[i].IsStatic to the check if a field is public and seems to work.

It will be an issue if someone has a class with public static variables that he wants serialized.

Make package source-only

Hi!
Thanks for the great package. Very useful in simple cases where Newtonsoft or System.Text.Json dependency is overkill )

May be it would be useful if it were package with only sources included which are added to the project as internal classes. In such scenario dependency on TinyJson also could be made compile-time only - and it would be great for internal usage

\uXXXX ?

Nice parser, would tell there are missing unicode escape chars - my test file generated by browser had'em (see bellow).
And in case U R interested in speed and memory improvements, maybe it would be better to replace StringBuilders by some string "pointer" class - my small test with 1/4TB JSON used 15,68% less memory and 9,4% less CPU.
But best should be to use single string and then only some pointers to that one, but it will probably need more changes in concept, so not sure if it worth (did not changed all _ unused options in my case)...
eltomjan@95ce352

var esc = "{"";
for(var i=8;i<128;i++) esc += String.fromCharCode(i);
esc += ""}";
var js = JSON.stringify(esc);
Result:
{"\b\t\n\u000b\f\r\u000e\u000f\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f !"#$%&'()*+,-./0123456789:;<=>?@abcdefghijklmnopqrstuvwxyz[\]^_`abcdefghijklmnopqrstuvwxyz{|}~�"}

Should this work on Windows 10 Core?

Hi,

I'm trying to write a Windows 10 Core app for my Raspberry Pi, and they shipped it with practically zero JSON Support. I was thrilled when I found your class here, but when I try to add it, I see red squiggles in Visual Studio.

Error CS1061 'Type' does not contain a definition for 'IsGenericType' and no extension method 'IsGenericType' accepting a first argument of type 'Type' could be found (are you missing a using directive or an assembly reference?) IoTCoreDefaultApp C:\temp\Iot\IoTCoreDefaultApp\TinyJson.cs 169 Active

Error CS1061 'Type' does not contain a definition for 'IsGenericType' and no extension method 'IsGenericType' accepting a first argument of type 'Type' could be found (are you missing a using directive or an assembly reference?) IoTCoreDefaultApp C:\temp\Iot\IoTCoreDefaultApp\TinyJson.cs 182 Active

Do not ignore dictionaries with non-string keys

throw exception or try to handle disctionary like this:

Index: JSONWriter.cs
@@ -63,14 +63,7 @@
             }
             else if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Dictionary<,>))
             {
-                Type keyType = type.GetGenericArguments()[0];
-                
-                //Refuse to output dictionary keys that aren't of type string
-                if (keyType != typeof(string))
-                {
-                    stringBuilder.Append("{}");
-                    return;
-                }
+                var keySet = new HashSet<string>();
 
                 stringBuilder.Append('{');
                 IDictionary dict = item as IDictionary;
@@ -77,12 +70,17 @@
                 bool isFirst = true;
                 foreach (object key in dict.Keys)
                 {
+                    string keyStr = key.ToString();
+                    if (keySet.Contains(keyStr))
+                        throw new Exception("Unsupported dictionary key type");
+                    else
+                        keySet.Add(keyStr);
                     if (isFirst)
                         isFirst = false;
                     else
                         stringBuilder.Append(',');
                     stringBuilder.Append('\"');
-                    stringBuilder.Append((string)key);
+                    stringBuilder.Append(keyStr);
                     stringBuilder.Append("\":");
                     AppendValue(stringBuilder, dict[key]);
                 }

FormatterServices is obsoleted in .NET 8.0

WARN:

SYSLIB0050	“FormatterServices” obsoleted :“Formatter-based serialization is obsolete and should not be used.”	JSONParser.cs

SRC:

[Obsolete("Formatter-based serialization is obsolete and should not be used.", DiagnosticId = "SYSLIB0050", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")]
public static class FormatterServices
{
    ///
}

An improvement

See the issue #47

Maybe add this functionality?
With something like: public static T FromJson<T>(this string json, object defaultObject)

Unicode's backslash lost problem

When I tries to convert a json to a Dictionary<string, object>, my Chinese characters (e.g. "\u94b1\u4e0d\u591f!") inside dictionary values will become "u94b1u4e0du591f!", thus make it not readable any more.

Writer get confused with calculated properties

Given the current class

using System;
using UnityEngine;

[Serializable]
public class SzVector3
{
    public Vector3 Value => new Vector3(x, y, z); // Buggy

    public float x;
    public float y;
    public float z;

    public SzVector3(Vector3 v)
    {
        x = v.x;
        y = v.y;
        z = v.z;
    }
}

the writer will fail to build a json representation of this object with exception: TargetParameterCountException: Number of parameters specified does not match the expected number.

if you change the calculated propertie to a method like so public Vector3 Value() => new Vector3(x, y, z);
it works.

I'm not a specialist so I can not help much more than that report

Thank you for that lib and for your time

Add To Readme, JSON to Class Converter

This is not issue, I think it good idea if you can add https://app.quicktype.io to the Readme, it parse JSON and generate the Class, it useful for known Json and save times writing the class.

Short how to:

  • open the website
  • paste your json
  • set Output features to Just Types or other
  • set Other options if needed* (detect boolean/int to false), ex: {"IwantAsString" : "12345"} or this parser will throw error because the parser try to convert "12345" (with quote) to long. But you can also fix the parser on Line 163 by prepend the line json = json.Trim('"');
  • Copy generated code to you project

Example how it can be very useful

Json code

{
    "FirstKey": {
        "SecondKey": "val",
        "ThirdKey": [1, 2]
    }
}

Generated class

namespace projectNamespace
{

    public partial class MyJsonClass
    {
        public FirstKey FirstKey { get; set; }
    }

    public partial class FirstKey
    {
        public string SecondKey { get; set; }
        public List<long> ThirdKey { get; set; }
    }
}

Access it

var jsonClass = File.ReadAllText("file.json").FromJson<MyJsonClass>(); 
jsonClass.FirstKey.SecondKey = "test";
jsonClass.FirstKey.ThirdKey.Add(3);

// VS

var jsonClass = File.ReadAllText("file.json").FromJson<Dictionary<string, Dictionary<string, string>>>(); 
jsonClass["FirstKey"]["SecondKey "] = "test"
jsonClass["FirstKey"]["ThirdKey"]... problematic

Normalise whitespace

Whitespace is a bit inconsistent in various files. Applying Microsoft's default Visual Studio "Format document" to create basic alignment

Backslashes trimmed

I'm parsing a JSON file and it looks like all backslashes are trimmed from the strings.

Suitable license attribution

@zanders3 I wanted to check you're happy with the attribution of the library and your work in the library we just open-sourced. - https://github.com/heroiclabs/nakama-dotnet

The README suggests we add this library as sources to a project which requires it.

Simply copy and paste the JSON Parser and/or the JSON Writer into your project. I also provide NuGet but I recommend the copy paste route ;)

That's what I've done but added it like so:

  • The source files have an MIT header at the top of each of them.
  • The folder with the sources has your MIT license file copied into it.
  • A note in the README mentions this project.

Let me know if you want anything changed. Thanks for the great work. 👍

Default values for values that didn't exist

If the json payload does not have some values to serialize them into a struct, how to set such values to a custom default?
Nullable types aren't the choice because I use .net framework 4.5.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.