├── LICENSE.meta ├── README.md.meta ├── package.json.meta ├── docs.meta ├── RedOwl.meta ├── RedOwl ├── Engine.meta ├── Examples.meta ├── Engine │ ├── RedOwl.unity-json.asmdef.meta │ ├── Json.cs.meta │ ├── JsonSerialization.cs.meta │ ├── RedOwl.unity-json.asmdef │ ├── JsonSerialization.cs │ └── Json.cs └── Examples │ ├── RedOwl.unity-json.examples.asmdef.meta │ ├── JsonExample.cs.meta │ ├── RedOwl.unity-json.examples.asmdef │ └── JsonExample.cs ├── package.json ├── .gitignore ├── LICENSE └── README.md /LICENSE.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 728d6682b5a3ac84e8cac753063619a8 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /README.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5de7e465414a85e4a9ebdf2b0285f5ae 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /package.json.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b4ebe581a05c0cc438e19cfab535d07b 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /docs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a250c60e6b0a9e74dadc159a1e028bab 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /RedOwl.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 979f69ba4293ce74db048a2692dd6509 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /RedOwl/Engine.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a8799b5d712a97c4cb755cc42c0e617f 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /RedOwl/Examples.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 51bab3e24185eea408409f842fb34051 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /RedOwl/Engine/RedOwl.unity-json.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8521c9557f492284fadb4cf46f4f5c65 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /RedOwl/Examples/RedOwl.unity-json.examples.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6618b98616895c14a9e5ff5c0d273116 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /RedOwl/Engine/Json.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1ef1bf08750693445a5133f3f7ce7c56 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /RedOwl/Engine/JsonSerialization.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e263031594ee0c1498048825822b2551 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /RedOwl/Examples/JsonExample.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b962714463c719741a79b649888f28e7 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /RedOwl/Engine/RedOwl.unity-json.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "RedOwl.unity-json", 3 | "references": [], 4 | "optionalUnityReferences": [], 5 | "includePlatforms": [], 6 | "excludePlatforms": [], 7 | "allowUnsafeCode": false, 8 | "overrideReferences": false, 9 | "precompiledReferences": [], 10 | "autoReferenced": true, 11 | "defineConstraints": [] 12 | } -------------------------------------------------------------------------------- /RedOwl/Examples/RedOwl.unity-json.examples.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "RedOwl.unity-json.examples", 3 | "references": [ 4 | "RedOwl.unity-json" 5 | ], 6 | "optionalUnityReferences": [], 7 | "includePlatforms": [], 8 | "excludePlatforms": [], 9 | "allowUnsafeCode": false, 10 | "overrideReferences": false, 11 | "precompiledReferences": [], 12 | "autoReferenced": true, 13 | "defineConstraints": [] 14 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "com.redowl.unity-json", 3 | "displayName": "RedOwl - Unity Json", 4 | "version": "1.0.0", 5 | "description": "Implements the JSON spec in a C# native way allowing easier interaction with JSON node trees.", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/red-owl-games/unity-json" 9 | }, 10 | "author": "Kyle Rockman", 11 | "license": "MIT", 12 | "keywords": [ 13 | "unity3d", 14 | "unity3d-package", 15 | "json", 16 | "serialization" 17 | ], 18 | "category": "RedOwl", 19 | "unity": "2018.4" 20 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | [Ll]ibrary/ 2 | [Tt]emp/ 3 | [Oo]bj/ 4 | [Bb]uild/ 5 | [Bb]uilds/ 6 | Assets/AssetStoreTools* 7 | 8 | # Visual Studio cache directory 9 | .vs/ 10 | 11 | # Autogenerated VS/MD/Consulo solution and project files 12 | ExportedObj/ 13 | .consulo/ 14 | *.csproj 15 | *.unityproj 16 | *.sln 17 | *.suo 18 | *.tmp 19 | *.user 20 | *.userprefs 21 | *.pidb 22 | *.booproj 23 | *.svd 24 | *.pdb 25 | *.opendb 26 | 27 | # Unity3D generated meta files 28 | *.pidb.meta 29 | *.pdb.meta 30 | 31 | # Unity3D Generated File On Crash Reports 32 | sysinfo.txt 33 | 34 | # Builds 35 | *.apk 36 | *.unitypackage 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Red Owl Games 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # unity-json 2 | Implements the JSON spec in a C# native way allowing for an easy interaction with the JSON spec 3 | 4 | ## Why ?!? 5 | 6 | Why another Unity json library? 7 | 8 | Well i found it a pretty open field and nothing out there supporting the actual Json Spec in a C# native way. 9 | 10 | This library is less about serialization/deserialization to Json (though it can do that) and more about crafting 11 | and inspecting complex Json objects. 12 | 13 | ## Whats it look like? 14 | 15 | ```cs 16 | // Create a Json Object 17 | Json data = new Json 18 | { 19 | ["John"] = new Json 20 | { 21 | {"age", 30}, 22 | {"height", 168.321}, 23 | {"position", new Vector2(1.025468f, 2.1f)}, 24 | {"rotation", Quaternion.identity}, 25 | { 26 | "city", new Json {"New York", Json.Null, true, "Los Angeles"} 27 | } 28 | }, 29 | ["justin"] = "test" 30 | }; 31 | // You can even implictly cast datatypes if needs be 32 | Json implict = 30; 33 | 34 | // Log the Json to see what your getting 35 | Debug.Log(data); 36 | 37 | // Serialize and Deserialize 38 | Json deserialized = Json.Deserialize(data.Serialize()); 39 | 40 | // Access data both keyed and indexed 41 | Debug.Log(deserialized["John"]["city"][2]); 42 | 43 | // Implicit type conversion 44 | Debug.Log(deserialized["John"]["age"] == 30); 45 | Debug.Log(deserialized["John"]["rotation"] == Quaternion.identity; 46 | // or explict if you need 47 | Debug.Log((Vector2) deserialized["position"]); 48 | Debug.Log((Quaternion) deserialized["rotation"]); 49 | ``` 50 | 51 | ### How is this better then something like FullSerializer or SimpleJSon 52 | 53 | I built this library mainly to work with custom JSON web API's in a c# way without having to create 54 | domain specific objects that match my web API's. It also allows me to easily send Unity datatypes in a 55 | Json compliant way which most unity Json serializers don't allow for. 56 | 57 | For Example 58 | 59 | ```cs 60 | Json data = new Json 61 | { 62 | ["John"] = new Json 63 | { 64 | {"age", 30}, 65 | {"position", new Vector2(1.025468f, 2.1f)}, 66 | {"rotation", Quaternion.identity} 67 | } 68 | }; 69 | ``` 70 | 71 | would net the json 72 | 73 | ```json 74 | {"John": {"age": 30, "position": {"x": 1.025468, "y": 2.1}, "rotation": {"x": 0, "y": 0, "z": 0, "w": 1}}} 75 | ``` 76 | 77 | Where as if you used something like FullSerializer or SimpleJson you'd get polluted with a bunch of metadata 78 | and type information garbage like the below 79 | 80 | ```json 81 | 82 | ``` 83 | 84 | If this project interests you please get in touch as I'd like to know about your usecases and make sure 85 | I'm covering them. I'd like this library to grow into a well used Json library for interacting with 86 | web-based Json API's so I have a few quality of life features i'd like to implement in the future. 87 | 88 | ## Installation 89 | 90 | You must be using Unity >= 2018.4! 91 | 92 | In your unity project root open Packages/manifest.json 93 | 94 | Add the following line to the dependencies section 95 | 96 | ``` 97 | "com.redowl.unity-json": "https://github.com/red-owl-games/unity-json.git", 98 | ``` 99 | 100 | Open Unity and the package should download automatically and you are ready to go! 101 | 102 | ```cs 103 | using RedOwl.Engine 104 | 105 | Json data = new Json(); 106 | ``` 107 | -------------------------------------------------------------------------------- /RedOwl/Examples/JsonExample.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using RedOwl.Engine; 3 | 4 | namespace RedOwl.Examples 5 | { 6 | 7 | public class JsonExample : MonoBehaviour 8 | { 9 | private string sampleJson = 10 | "{" + 11 | "\"employee\":{ \"name\":\"John\", \"age\":30, \"height\":168.321, \"city\":[\"New York\", null, true, {\"x\": 1, \"y\": 2}]}" + 12 | "}"; 13 | 14 | public void Start() 15 | { 16 | // Create a Json Object 17 | Json data = new Json(); 18 | 19 | // Or using collection initializers 20 | Json collection = new Json 21 | { 22 | ["John"] = new Json 23 | { 24 | {"age", 30}, 25 | {"height", 168.321}, // supports all c# primative datatypes 26 | {"position", new Vector2(1.025468f, 2.1f)}, // Can use select Unity datatypes too! 27 | {"rotation", Quaternion.identity}, 28 | { 29 | "city", new Json {"New York", Json.Null, true, "Los Angeles"} 30 | } // supports arrays and nested objects 31 | }, 32 | ["justin"] = "test" // Allows for asymmetric datatype collections 33 | }; 34 | // Or implictly cast 35 | Json implict = 30; 36 | 37 | // OR build up over time 38 | data["coins"] = 99; 39 | data["health"] = -83.2f; 40 | data["position"] = new Vector2(1, 2); 41 | data["rotation"] = Quaternion.identity; 42 | data["unicode"] = "€öäüß✓✓✓✓"; // you can also use unicode strings 43 | data["foo"]["bar"]["baz"]["value"] = 20.0; // you can easily create nested objects 44 | data["array"]["cities"] = new Json {"New York", "Los Angeles", "Austin"}; 45 | 46 | 47 | // Log the Json to see what your getting 48 | Debug.Log(data); 49 | //{"coins": 99, "health": -83.2, "position": {"x": 1, "y": 2}, "rotation": {"x": 0, "y": 0, "z": 0, "w": 1}, "unicode": "€öäüß✓✓✓✓", "foo": {"bar": {"baz": {"value": 20}}}, "array": {"cities": ["New York", "Los Angeles", "Austin"]}} 50 | Debug.Log(collection); 51 | //{"John": {"age": 30, "height": 168.321, "position": {"x": 1.025468, "y": 2.1}, "rotation": {"x": 0, "y": 0, "z": 0, "w": 1}, "city": ["New York", null, true, "Los Angeles"]}, "justin": "test"} 52 | 53 | // Serialize the Json 54 | // Standard spec is the kind of Json you'd send at a web API 55 | string standardSpec = data.ToString(); 56 | // Typed spec allows for deserializing back to original types for better use in unity 57 | string typedSpec = data.Serialize(); 58 | // Typed spec can easily be decompressed or converted to binary to save space if needed 59 | 60 | Debug.Log(standardSpec); 61 | Debug.Log(typedSpec); 62 | 63 | // Deserialize the Json 64 | Json deserialized = Json.Deserialize(typedSpec); 65 | 66 | // Even random strings of data with no type information 67 | Json random = Json.Deserialize(sampleJson); 68 | Debug.Log(random); 69 | 70 | // Access properties of both keyed and indexed 71 | Debug.Log(deserialized["array"]["cities"][2]); 72 | 73 | // Implicit type conversion 74 | Debug.Log(deserialized["coins"] == 99); 75 | Debug.Log(deserialized["position"] == new Vector2(1, 2)); 76 | Debug.Log(deserialized["position"] == new Vector2(2, 1)); 77 | // or explict if you need - ** only works if deserialized from a typedSpec ** 78 | Debug.Log((Vector2) deserialized["position"]); 79 | Debug.Log((Quaternion) deserialized["rotation"]); 80 | 81 | // Throws assert on invalid conversion 82 | Debug.Log(deserialized["unicode"] == Quaternion.identity); 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /RedOwl/Engine/JsonSerialization.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Text; 5 | using UnityEngine; 6 | 7 | namespace RedOwl.Engine 8 | { 9 | public static class JsonSerialization 10 | { 11 | #region Reader 12 | 13 | private static StringReader _reader; 14 | 15 | private const string WhiteSpace = " \t\n\r"; 16 | private const string WordBreak = " \t\n\r{}[],:\""; 17 | 18 | private enum TOKEN 19 | { 20 | NONE, 21 | CURLY_OPEN, 22 | CURLY_CLOSE, 23 | SQUARED_OPEN, 24 | SQUARED_CLOSE, 25 | COLON, 26 | COMMA, 27 | STRING, 28 | NUMBER, 29 | TRUE, 30 | FALSE, 31 | NULL 32 | }; 33 | 34 | private static char PeekChar => Convert.ToChar(_reader.Peek()); 35 | 36 | private static char NextChar => Convert.ToChar(_reader.Read()); 37 | 38 | private static string NextWord 39 | { 40 | get { 41 | StringBuilder word = new StringBuilder(); 42 | 43 | while (WordBreak.IndexOf(PeekChar) == -1) { 44 | word.Append(NextChar); 45 | 46 | if (_reader.Peek() == -1) { 47 | break; 48 | } 49 | } 50 | 51 | return word.ToString(); 52 | } 53 | } 54 | 55 | private static void EatWhitespace() 56 | { 57 | while (WhiteSpace.IndexOf(PeekChar) != -1) { 58 | _reader.Read(); 59 | 60 | if (_reader.Peek() == -1) { 61 | break; 62 | } 63 | } 64 | } 65 | 66 | private static TOKEN NextToken 67 | { 68 | get { 69 | EatWhitespace(); 70 | 71 | if (_reader.Peek() == -1) { 72 | return TOKEN.NONE; 73 | } 74 | 75 | char c = PeekChar; 76 | switch (c) { 77 | case '{': 78 | return TOKEN.CURLY_OPEN; 79 | case '}': 80 | _reader.Read(); 81 | return TOKEN.CURLY_CLOSE; 82 | case '[': 83 | return TOKEN.SQUARED_OPEN; 84 | case ']': 85 | _reader.Read(); 86 | return TOKEN.SQUARED_CLOSE; 87 | case ',': 88 | _reader.Read(); 89 | return TOKEN.COMMA; 90 | case '"': 91 | return TOKEN.STRING; 92 | case ':': 93 | return TOKEN.COLON; 94 | case '0': 95 | case '1': 96 | case '2': 97 | case '3': 98 | case '4': 99 | case '5': 100 | case '6': 101 | case '7': 102 | case '8': 103 | case '9': 104 | case '-': 105 | return TOKEN.NUMBER; 106 | } 107 | 108 | string word = NextWord; 109 | 110 | switch (word) { 111 | case "false": 112 | return TOKEN.FALSE; 113 | case "true": 114 | return TOKEN.TRUE; 115 | case "null": 116 | return TOKEN.NULL; 117 | } 118 | 119 | return TOKEN.NONE; 120 | } 121 | } 122 | 123 | private static Json ParseValue() 124 | { 125 | return ParseByToken(NextToken); 126 | } 127 | 128 | private static Json ParseByToken(TOKEN token) 129 | { 130 | switch (token) { 131 | case TOKEN.STRING: 132 | return ParseString(); 133 | case TOKEN.NUMBER: 134 | return ParseNumber(); 135 | case TOKEN.CURLY_OPEN: 136 | // ditch opening brace 137 | _reader.Read(); 138 | return ParseObject(); 139 | case TOKEN.SQUARED_OPEN: 140 | // ditch opening bracket 141 | _reader.Read(); 142 | return ParseArray(); 143 | case TOKEN.TRUE: 144 | return true; 145 | case TOKEN.FALSE: 146 | return false; 147 | case TOKEN.NULL: 148 | return Json.Null; 149 | default: 150 | return Json.Null; 151 | } 152 | } 153 | 154 | private static string ParseString() 155 | { 156 | StringBuilder s = new StringBuilder(); 157 | 158 | // ditch opening quote 159 | _reader.Read(); 160 | 161 | bool parsing = true; 162 | while (parsing) { 163 | 164 | if (_reader.Peek() == -1) { 165 | parsing = false; 166 | break; 167 | } 168 | 169 | char c = NextChar; 170 | switch (c) { 171 | case '"': 172 | parsing = false; 173 | break; 174 | case '\\': 175 | if (_reader.Peek() == -1) { 176 | parsing = false; 177 | break; 178 | } 179 | 180 | c = NextChar; 181 | switch (c) { 182 | case '"': 183 | case '\\': 184 | case '/': 185 | s.Append(c); 186 | break; 187 | case 'b': 188 | s.Append('\b'); 189 | break; 190 | case 'f': 191 | s.Append('\f'); 192 | break; 193 | case 'n': 194 | s.Append('\n'); 195 | break; 196 | case 'r': 197 | s.Append('\r'); 198 | break; 199 | case 't': 200 | s.Append('\t'); 201 | break; 202 | case 'u': 203 | StringBuilder hex = new StringBuilder(); 204 | 205 | for (int i=0; i< 4; i++) { 206 | hex.Append(NextChar); 207 | } 208 | 209 | s.Append((char) Convert.ToInt32(hex.ToString(), 16)); 210 | break; 211 | } 212 | break; 213 | default: 214 | s.Append(c); 215 | break; 216 | } 217 | } 218 | 219 | return s.ToString(); 220 | } 221 | 222 | private static double ParseNumber() 223 | { 224 | string number = NextWord; 225 | double.TryParse(number, out double parsedDouble); 226 | return parsedDouble; 227 | } 228 | 229 | private static Json ParseArray() 230 | { 231 | List array = new List(); 232 | 233 | bool parsing = true; 234 | while (parsing) { 235 | TOKEN nextToken = NextToken; 236 | 237 | switch (nextToken) { 238 | case TOKEN.NONE: 239 | return null; 240 | case TOKEN.COMMA: 241 | continue; 242 | case TOKEN.SQUARED_CLOSE: 243 | parsing = false; 244 | break; 245 | default: 246 | array.Add(ParseByToken(nextToken)); 247 | break; 248 | } 249 | } 250 | 251 | return new Json(array); 252 | } 253 | 254 | private static Json ParseObject() 255 | { 256 | Dictionary data = new Dictionary(); 257 | 258 | while (true) { 259 | switch (NextToken) { 260 | case TOKEN.NONE: 261 | return null; 262 | case TOKEN.COMMA: 263 | continue; 264 | case TOKEN.CURLY_CLOSE when data.ContainsKey("JsonType") && data.ContainsKey("DataType"): 265 | return Json.FromSerialization(data["JsonType"], data["DataType"], data["Value"]); 266 | case TOKEN.CURLY_CLOSE: 267 | return new Json(data); 268 | default: 269 | // key 270 | string key = ParseString(); 271 | if (key == null) { 272 | return null; 273 | } 274 | // : 275 | if (NextToken != TOKEN.COLON) { 276 | return null; 277 | } 278 | // ditch the colon 279 | _reader.Read(); 280 | 281 | // value 282 | data[key] = ParseValue(); 283 | break; 284 | } 285 | } 286 | } 287 | 288 | #endregion 289 | 290 | public static string Serialize(Json data) 291 | { 292 | StringWriter writer = new StringWriter(); 293 | data.Write(writer, true); 294 | return writer.ToString(); 295 | } 296 | 297 | public static Json Deserialize(string json) 298 | { 299 | _reader = new StringReader(json); 300 | return ParseValue(); 301 | } 302 | 303 | } 304 | } -------------------------------------------------------------------------------- /RedOwl/Engine/Json.cs: -------------------------------------------------------------------------------- 1 | 2 | 3 | using System; 4 | using System.Collections; 5 | using System.Collections.Generic; 6 | using System.Globalization; 7 | using System.IO; 8 | using UnityEngine; 9 | using UnityEngine.Assertions; 10 | 11 | namespace RedOwl.Engine 12 | { 13 | /// 14 | /// We need to merge the Json and JsonArray classes 15 | /// Both can use a dictionary to store their data 16 | /// We need an Enum to track if the Json class is : NotSet, IsValue, IsContainer 17 | /// We might also need move all the implict value conversions into this class 18 | /// The class will not inherit from dictionary and will need to store a dictionray for IsContainer and IJsonValue for IsValue 19 | /// Maybe we actually have an Enum for JsonValueType : Null, String, Bool, Number, Array, Object ? 20 | /// 21 | /// Lastly we need to implement json string parsing and probably convert to Serialize/Deserialize methods where ToString calls Serialize 22 | /// Well need to look at the msgPack jsonReader/jsonWriter classes to understand string parsing tokenization 23 | /// 24 | 25 | public class Json : IEnumerable 26 | { 27 | public enum JsonTypes 28 | { 29 | Undefined, 30 | Null, 31 | String, 32 | Boolean, 33 | Number, 34 | Array, 35 | Object 36 | } 37 | 38 | public enum DataTypes 39 | { 40 | Undefined, 41 | Primitive, 42 | Container, 43 | Uri, 44 | Guid, 45 | DateTime, 46 | DateTimeOffset, 47 | TimeSpan, 48 | Color, 49 | Vector, 50 | Quaternion, 51 | Bounds, 52 | Rect 53 | } 54 | 55 | internal JsonTypes JsonType = JsonTypes.Undefined; 56 | internal DataTypes DataType = DataTypes.Undefined; 57 | 58 | private string _string; 59 | private bool _bool; 60 | private double _number; 61 | 62 | private List _array = new List(); 63 | private Dictionary _container = new Dictionary(); 64 | 65 | public Json this[int index] 66 | { 67 | get => _array[index]; 68 | set 69 | { 70 | Assert.IsTrue(JsonType == JsonTypes.Array || JsonType == JsonTypes.Undefined); 71 | JsonType = JsonTypes.Array; 72 | DataType = DataTypes.Container; 73 | _array[index] = value; 74 | } 75 | } 76 | 77 | public Json this[string key] 78 | { 79 | get 80 | { 81 | if (!_container.ContainsKey(key)) _container[key] = Json.Object; 82 | return _container[key]; 83 | } 84 | set 85 | { 86 | Assert.IsTrue(JsonType == JsonTypes.Object || JsonType == JsonTypes.Undefined); 87 | JsonType = JsonTypes.Object; 88 | DataType = DataTypes.Container; 89 | _container[key] = value; 90 | } 91 | } 92 | 93 | public override string ToString() 94 | { 95 | switch (JsonType) 96 | { 97 | case JsonTypes.Undefined: 98 | case JsonTypes.Null: 99 | return "null"; 100 | case JsonTypes.String: 101 | return _string; 102 | case JsonTypes.Boolean: 103 | return _bool.ToString(); 104 | case JsonTypes.Number: 105 | return _number.ToString(CultureInfo.CurrentCulture); 106 | case JsonTypes.Array: 107 | StringWriter arrayWriter = new StringWriter(); 108 | Write(arrayWriter); 109 | return arrayWriter.ToString(); 110 | case JsonTypes.Object: 111 | StringWriter containerWriter = new StringWriter(); 112 | Write(containerWriter); 113 | return containerWriter.ToString(); 114 | default: 115 | throw new ArgumentOutOfRangeException(); 116 | } 117 | } 118 | 119 | public IEnumerator GetEnumerator() 120 | { 121 | switch (JsonType) 122 | { 123 | case JsonTypes.Array: 124 | return _array.GetEnumerator(); 125 | case JsonTypes.Object: 126 | return _container.GetEnumerator(); 127 | } 128 | throw new ArgumentOutOfRangeException(); 129 | } 130 | 131 | public void Add(Json value) 132 | { 133 | Assert.IsTrue(JsonType == JsonTypes.Array || JsonType == JsonTypes.Undefined); 134 | JsonType = JsonTypes.Array; 135 | DataType = DataTypes.Container; 136 | _array.Add(value); 137 | } 138 | 139 | public void Add(string key, Json value) 140 | { 141 | Assert.IsTrue(JsonType == JsonTypes.Object || JsonType == JsonTypes.Undefined); 142 | JsonType = JsonTypes.Object; 143 | DataType = DataTypes.Container; 144 | _container.Add(key, value); 145 | } 146 | 147 | #region Types 148 | 149 | private string String 150 | { 151 | get 152 | { 153 | Assert.IsTrue(JsonType == JsonTypes.String && DataType == DataTypes.Primitive); 154 | return _string; 155 | } 156 | set 157 | { 158 | JsonType = JsonTypes.String; 159 | DataType = DataTypes.Primitive; 160 | _string = value; 161 | } 162 | } 163 | 164 | private bool Bool 165 | { 166 | get 167 | { 168 | Assert.IsTrue(JsonType == JsonTypes.Boolean && DataType == DataTypes.Primitive); 169 | return _bool; 170 | } 171 | set 172 | { 173 | JsonType = JsonTypes.Boolean; 174 | DataType = DataTypes.Primitive; 175 | _bool = value; 176 | } 177 | } 178 | 179 | private double Number 180 | { 181 | get 182 | { 183 | Assert.IsTrue(JsonType == JsonTypes.Number && DataType == DataTypes.Primitive); 184 | return _number; 185 | } 186 | set 187 | { 188 | JsonType = JsonTypes.Number; 189 | DataType = DataTypes.Primitive; 190 | _number = value; 191 | } 192 | } 193 | 194 | private Uri Uri 195 | { 196 | get 197 | { 198 | Assert.IsTrue(JsonType == JsonTypes.String && DataType == DataTypes.Uri); 199 | return new Uri(_string); 200 | } 201 | set 202 | { 203 | JsonType = JsonTypes.String; 204 | DataType = DataTypes.Uri; 205 | _string = value.OriginalString; 206 | } 207 | } 208 | 209 | private Guid Guid 210 | { 211 | get 212 | { 213 | Assert.IsTrue(JsonType == JsonTypes.String && DataType == DataTypes.Guid); 214 | return Guid.Parse(_string); 215 | } 216 | set 217 | { 218 | JsonType = JsonTypes.String; 219 | DataType = DataTypes.Guid; 220 | _string = value.ToString(); 221 | } 222 | } 223 | 224 | private DateTime DateTime 225 | { 226 | get 227 | { 228 | Assert.IsTrue(JsonType == JsonTypes.String && DataType == DataTypes.DateTime); 229 | return DateTime.SpecifyKind(DateTime.Parse(_string), DateTimeKind.Utc); 230 | } 231 | set 232 | { 233 | JsonType = JsonTypes.String; 234 | DataType = DataTypes.DateTime; 235 | _string = DateTime.SpecifyKind(value, DateTimeKind.Utc).ToString(CultureInfo.CurrentCulture); 236 | } 237 | } 238 | 239 | private DateTimeOffset DateTimeOffset 240 | { 241 | get 242 | { 243 | Assert.IsTrue(JsonType == JsonTypes.String && DataType == DataTypes.DateTimeOffset); 244 | return DateTimeOffset.Parse(_string); 245 | } 246 | set 247 | { 248 | JsonType = JsonTypes.String; 249 | DataType = DataTypes.DateTimeOffset; 250 | _string = value.ToString(CultureInfo.CurrentCulture); 251 | } 252 | } 253 | 254 | private TimeSpan TimeSpan 255 | { 256 | get 257 | { 258 | Assert.IsTrue(JsonType == JsonTypes.Object && DataType == DataTypes.TimeSpan); 259 | return new TimeSpan((long)_number); 260 | } 261 | set 262 | { 263 | JsonType = JsonTypes.Object; 264 | DataType = DataTypes.TimeSpan; 265 | _number = value.Ticks; 266 | } 267 | } 268 | 269 | private Color Color 270 | { 271 | get 272 | { 273 | Assert.IsTrue(JsonType == JsonTypes.Object && DataType == DataTypes.Color); 274 | return new Color(this["r"], this["g"], this["b"], this["a"]); 275 | } 276 | set 277 | { 278 | JsonType = JsonTypes.Object; 279 | DataType = DataTypes.Color; 280 | _container = new Dictionary { {"r", value.r}, {"g", value.g}, {"b", value.b}, {"a", value.a}}; 281 | } 282 | } 283 | 284 | private Color32 Color32 285 | { 286 | get 287 | { 288 | Assert.IsTrue(JsonType == JsonTypes.Object && DataType == DataTypes.Color); 289 | return new Color(this["r"], this["g"], this["b"], this["a"]); 290 | } 291 | set 292 | { 293 | JsonType = JsonTypes.Object; 294 | DataType = DataTypes.Color; 295 | _container = new Dictionary { {"r", value.r}, {"g", value.g}, {"b", value.b}, {"a", value.a}}; 296 | } 297 | } 298 | 299 | private Vector2 Vector2 300 | { 301 | get 302 | { 303 | Assert.IsTrue(JsonType == JsonTypes.Object && DataType == DataTypes.Vector); 304 | return new Vector2(this["x"], this["y"]); 305 | } 306 | set 307 | { 308 | JsonType = JsonTypes.Object; 309 | DataType = DataTypes.Vector; 310 | _container = new Dictionary { {"x", value.x}, {"y", value.y}}; 311 | } 312 | } 313 | 314 | private Vector3 Vector3 315 | { 316 | get 317 | { 318 | Assert.IsTrue(JsonType == JsonTypes.Object && DataType == DataTypes.Vector); 319 | return new Vector3(this["x"], this["y"], this["z"]); 320 | } 321 | set 322 | { 323 | JsonType = JsonTypes.Object; 324 | DataType = DataTypes.Vector; 325 | _container = new Dictionary { {"x", value.x}, {"y", value.y}, {"z", value.z}}; 326 | } 327 | } 328 | 329 | private Vector4 Vector4 330 | { 331 | get 332 | { 333 | Assert.IsTrue(JsonType == JsonTypes.Object && (DataType == DataTypes.Vector || DataType == DataTypes.Quaternion)); 334 | return new Vector4(this["x"], this["y"], this["z"], this["w"]); 335 | } 336 | set 337 | { 338 | JsonType = JsonTypes.Object; 339 | DataType = DataTypes.Vector; 340 | _container = new Dictionary { {"x", value.x}, {"y", value.y}, {"z", value.z}, {"w", value.w}}; 341 | } 342 | } 343 | 344 | private Quaternion Quaternion 345 | { 346 | get 347 | { 348 | Assert.IsTrue(JsonType == JsonTypes.Object && (DataType == DataTypes.Vector || DataType == DataTypes.Quaternion)); 349 | return new Quaternion(this["x"], this["y"], this["z"], this["w"]); 350 | } 351 | set 352 | { 353 | JsonType = JsonTypes.Object; 354 | DataType = DataTypes.Quaternion; 355 | _container = new Dictionary { {"x", value.x}, {"y", value.y}, {"z", value.z}, {"w", value.w}}; 356 | } 357 | } 358 | 359 | private Bounds Bounds 360 | { 361 | get 362 | { 363 | Assert.IsTrue(JsonType == JsonTypes.Object && DataType == DataTypes.Bounds); 364 | return new Bounds(this["center"], this["size"]); 365 | } 366 | set 367 | { 368 | JsonType = JsonTypes.Object; 369 | DataType = DataTypes.Bounds; 370 | _container = new Dictionary { {"center", value.center}, {"size", value.size}}; 371 | } 372 | } 373 | 374 | private Rect Rect 375 | { 376 | get 377 | { 378 | Assert.IsTrue(JsonType == JsonTypes.Object && DataType == DataTypes.Rect); 379 | return new Rect(this["x"], this["y"], this["width"], this["height"]); 380 | } 381 | set 382 | { 383 | JsonType = JsonTypes.Object; 384 | DataType = DataTypes.Rect; 385 | _container = new Dictionary { {"x", value.x}, {"y", value.y}, {"width", value.width}, {"height", value.height}}; 386 | } 387 | } 388 | 389 | #endregion 390 | 391 | #region Constructors 392 | 393 | public Json() {} 394 | public Json(string value) { String = value; } 395 | public Json(bool value) { Bool = value; } 396 | public Json(double value) { Number = value; } 397 | public Json(Uri value) { Uri = value; } 398 | public Json(Guid value) { Guid = value; } 399 | public Json(DateTime value) { DateTime = value; } 400 | public Json(DateTimeOffset value) { DateTimeOffset = value; } 401 | public Json(TimeSpan value) { TimeSpan = value; } 402 | public Json(Color value) { Color = value; } 403 | public Json(Color32 value) { Color32 = value; } 404 | public Json(Vector2 value) { Vector2 = value; } 405 | public Json(Vector3 value) { Vector3 = value; } 406 | public Json(Vector4 value) { Vector4 = value; } 407 | public Json(Quaternion value) { Quaternion = value; } 408 | public Json(Bounds value) { Bounds = value; } 409 | public Json(Rect value) { Rect = value; } 410 | 411 | public Json(IEnumerable data) 412 | { 413 | JsonType = JsonTypes.Array; 414 | DataType = DataTypes.Container; 415 | _array = new List(data); 416 | } 417 | 418 | public Json(IDictionary data) 419 | { 420 | JsonType = JsonTypes.Object; 421 | DataType = DataTypes.Container; 422 | _container = new Dictionary(data); 423 | } 424 | 425 | public static Json Null => new Json { JsonType = JsonTypes.Null, DataType = DataTypes.Primitive }; 426 | public static Json Array => new Json { JsonType = JsonTypes.Array, DataType = DataTypes.Container }; 427 | public static Json Object => new Json { JsonType = JsonTypes.Object, DataType = DataTypes.Container }; 428 | 429 | #endregion 430 | 431 | #region ToJsonType 432 | 433 | public static implicit operator Json(string value) => new Json(value); 434 | public static implicit operator Json(string[] value) => new Json(System.Array.ConvertAll(value, x => (Json)x)); 435 | public static implicit operator Json(List value) => new Json(System.Array.ConvertAll(value.ToArray(), x => (Json)x)); 436 | public static implicit operator Json(bool value) => new Json(value); 437 | public static implicit operator Json(bool[] value) => new Json(System.Array.ConvertAll(value, x => (Json)x)); 438 | public static implicit operator Json(List value) => new Json(System.Array.ConvertAll(value.ToArray(), x => (Json)x)); 439 | public static implicit operator Json(float value) => new Json((double)(decimal)value); 440 | public static implicit operator Json(float[] value) => new Json(System.Array.ConvertAll(value, x => (Json)x)); 441 | public static implicit operator Json(List value) => new Json(System.Array.ConvertAll(value.ToArray(), x => (Json)x)); 442 | public static implicit operator Json(double value) => new Json(value); 443 | public static implicit operator Json(double[] value) => new Json(System.Array.ConvertAll(value, x => (Json)x)); 444 | public static implicit operator Json(List value) => new Json(System.Array.ConvertAll(value.ToArray(), x => (Json)x)); 445 | public static implicit operator Json(decimal value) => new Json((double)value); 446 | public static implicit operator Json(decimal[] value) => new Json(System.Array.ConvertAll(value, x => (Json)x)); 447 | public static implicit operator Json(List value) => new Json(System.Array.ConvertAll(value.ToArray(), x => (Json)x)); 448 | public static implicit operator Json(short value) => new Json(value); 449 | public static implicit operator Json(short[] value) => new Json(System.Array.ConvertAll(value, x => (Json)x)); 450 | public static implicit operator Json(List value) => new Json(System.Array.ConvertAll(value.ToArray(), x => (Json)x)); 451 | public static implicit operator Json(int value) => new Json(value); 452 | public static implicit operator Json(int[] value) => new Json(System.Array.ConvertAll(value, x => (Json)x)); 453 | public static implicit operator Json(List value) => new Json(System.Array.ConvertAll(value.ToArray(), x => (Json)x)); 454 | public static implicit operator Json(long value) => new Json(value); 455 | public static implicit operator Json(long[] value) => new Json(System.Array.ConvertAll(value, x => (Json)x)); 456 | public static implicit operator Json(List value) => new Json(System.Array.ConvertAll(value.ToArray(), x => (Json)x)); 457 | public static implicit operator Json(ushort value) => new Json(value); 458 | public static implicit operator Json(ushort[] value) => new Json(System.Array.ConvertAll(value, x => (Json)x)); 459 | public static implicit operator Json(List value) => new Json(System.Array.ConvertAll(value.ToArray(), x => (Json)x)); 460 | public static implicit operator Json(uint value) => new Json(value); 461 | public static implicit operator Json(uint[] value) => new Json(System.Array.ConvertAll(value, x => (Json)x)); 462 | public static implicit operator Json(List value) => new Json(System.Array.ConvertAll(value.ToArray(), x => (Json)x)); 463 | public static implicit operator Json(ulong value) => new Json(value); 464 | public static implicit operator Json(ulong[] value) => new Json(System.Array.ConvertAll(value, x => (Json)x)); 465 | public static implicit operator Json(List value) => new Json(System.Array.ConvertAll(value.ToArray(), x => (Json)x)); 466 | public static implicit operator Json(sbyte value) => new Json(value); 467 | public static implicit operator Json(sbyte[] value) => new Json(System.Array.ConvertAll(value, x => (Json)x)); 468 | public static implicit operator Json(List value) => new Json(System.Array.ConvertAll(value.ToArray(), x => (Json)x)); 469 | public static implicit operator Json(byte value) => new Json(value); 470 | public static implicit operator Json(byte[] value) => new Json(System.Array.ConvertAll(value, x => (Json)x)); 471 | public static implicit operator Json(List value) => new Json(System.Array.ConvertAll(value.ToArray(), x => (Json)x)); 472 | 473 | public static implicit operator Json(Uri value) => new Json(value); 474 | public static implicit operator Json(Uri[] value) => new Json(System.Array.ConvertAll(value, x => (Json)x)); 475 | public static implicit operator Json(List value) => new Json(System.Array.ConvertAll(value.ToArray(), x => (Json)x)); 476 | public static implicit operator Json(Guid value) => new Json(value); 477 | public static implicit operator Json(Guid[] value) => new Json(System.Array.ConvertAll(value, x => (Json)x)); 478 | public static implicit operator Json(List value) => new Json(System.Array.ConvertAll(value.ToArray(), x => (Json)x)); 479 | public static implicit operator Json(DateTime value) => new Json(value); 480 | public static implicit operator Json(DateTime[] value) => new Json(System.Array.ConvertAll(value, x => (Json)x)); 481 | public static implicit operator Json(List value) => new Json(System.Array.ConvertAll(value.ToArray(), x => (Json)x)); 482 | public static implicit operator Json(DateTimeOffset value) => new Json(value); 483 | public static implicit operator Json(DateTimeOffset[] value) => new Json(System.Array.ConvertAll(value, x => (Json)x)); 484 | public static implicit operator Json(List value) => new Json(System.Array.ConvertAll(value.ToArray(), x => (Json)x)); 485 | public static implicit operator Json(TimeSpan value) => new Json(value); 486 | public static implicit operator Json(TimeSpan[] value) => new Json(System.Array.ConvertAll(value, x => (Json)x)); 487 | public static implicit operator Json(List value) => new Json(System.Array.ConvertAll(value.ToArray(), x => (Json)x)); 488 | public static implicit operator Json(Color value) => new Json(value); 489 | public static implicit operator Json(Color[] value) => new Json(System.Array.ConvertAll(value, x => (Json)x)); 490 | public static implicit operator Json(List value) => new Json(System.Array.ConvertAll(value.ToArray(), x => (Json)x)); 491 | public static implicit operator Json(Color32 value) => new Json(value); 492 | public static implicit operator Json(Color32[] value) => new Json(System.Array.ConvertAll(value, x => (Json)x)); 493 | public static implicit operator Json(List value) => new Json(System.Array.ConvertAll(value.ToArray(), x => (Json)x)); 494 | public static implicit operator Json(Vector2 value) => new Json(value); 495 | public static implicit operator Json(Vector2[] value) => new Json(System.Array.ConvertAll(value, x => (Json)x)); 496 | public static implicit operator Json(List value) => new Json(System.Array.ConvertAll(value.ToArray(), x => (Json)x)); 497 | public static implicit operator Json(Vector3 value) => new Json(value); 498 | public static implicit operator Json(Vector3[] value) => new Json(System.Array.ConvertAll(value, x => (Json)x)); 499 | public static implicit operator Json(List value) => new Json(System.Array.ConvertAll(value.ToArray(), x => (Json)x)); 500 | public static implicit operator Json(Vector4 value) => new Json(value); 501 | public static implicit operator Json(Vector4[] value) => new Json(System.Array.ConvertAll(value, x => (Json)x)); 502 | public static implicit operator Json(List value) => new Json(System.Array.ConvertAll(value.ToArray(), x => (Json)x)); 503 | public static implicit operator Json(Quaternion value) => new Json(value); 504 | public static implicit operator Json(Quaternion[] value) => new Json(System.Array.ConvertAll(value, x => (Json)x)); 505 | public static implicit operator Json(List value) => new Json(System.Array.ConvertAll(value.ToArray(), x => (Json)x)); 506 | public static implicit operator Json(Bounds value) => new Json(value); 507 | public static implicit operator Json(Bounds[] value) => new Json(System.Array.ConvertAll(value, x => (Json)x)); 508 | public static implicit operator Json(List value) => new Json(System.Array.ConvertAll(value.ToArray(), x => (Json)x)); 509 | public static implicit operator Json(Rect value) => new Json(value); 510 | public static implicit operator Json(Rect[] value) => new Json(System.Array.ConvertAll(value, x => (Json)x)); 511 | public static implicit operator Json(List value) => new Json(System.Array.ConvertAll(value.ToArray(), x => (Json)x)); 512 | 513 | #endregion 514 | 515 | #region ToOtherTypes 516 | 517 | public static implicit operator string(Json value) => value.String; 518 | public static implicit operator string[](Json value) => value._array.ConvertAll(x => (string)x).ToArray(); 519 | public static implicit operator List(Json value) => value._array.ConvertAll(x => (string)x); 520 | public static implicit operator bool(Json value) => value.Bool; 521 | public static implicit operator bool[](Json value) => value._array.ConvertAll(x => (bool)x).ToArray(); 522 | public static implicit operator List(Json value) => value._array.ConvertAll(x => (bool)x); 523 | public static implicit operator float(Json value) => (float)value.Number; 524 | public static implicit operator float[](Json value) => value._array.ConvertAll(x => (float)x).ToArray(); 525 | public static implicit operator List(Json value) => value._array.ConvertAll(x => (float)x); 526 | public static implicit operator double(Json value) => value.Number; 527 | public static implicit operator double[](Json value) => value._array.ConvertAll(x => (double)x).ToArray(); 528 | public static implicit operator List(Json value) => value._array.ConvertAll(x => (double)x); 529 | public static implicit operator decimal(Json value) => (decimal)value.Number; 530 | public static implicit operator decimal[](Json value) => value._array.ConvertAll(x => (decimal)x).ToArray(); 531 | public static implicit operator List(Json value) => value._array.ConvertAll(x => (decimal)x); 532 | public static implicit operator short(Json value) => (short)value.Number; 533 | public static implicit operator short[](Json value) => value._array.ConvertAll(x => (short)x).ToArray(); 534 | public static implicit operator List(Json value) => value._array.ConvertAll(x => (short)x); 535 | public static implicit operator int(Json value) => (int)value.Number; 536 | public static implicit operator int[](Json value) => value._array.ConvertAll(x => (int)x).ToArray(); 537 | public static implicit operator List(Json value) => value._array.ConvertAll(x => (int)x); 538 | public static implicit operator long(Json value) => (long)value.Number; 539 | public static implicit operator long[](Json value) => value._array.ConvertAll(x => (long)x).ToArray(); 540 | public static implicit operator List(Json value) => value._array.ConvertAll(x => (long)x); 541 | public static implicit operator ushort(Json value) => (ushort)value.Number; 542 | public static implicit operator ushort[](Json value) => value._array.ConvertAll(x => (ushort)x).ToArray(); 543 | public static implicit operator List(Json value) => value._array.ConvertAll(x => (ushort)x); 544 | public static implicit operator uint(Json value) => (uint)value.Number; 545 | public static implicit operator uint[](Json value) => value._array.ConvertAll(x => (uint)x).ToArray(); 546 | public static implicit operator List(Json value) => value._array.ConvertAll(x => (uint)x); 547 | public static implicit operator ulong(Json value) => (ulong)value.Number; 548 | public static implicit operator ulong[](Json value) => value._array.ConvertAll(x => (ulong)x).ToArray(); 549 | public static implicit operator List(Json value) => value._array.ConvertAll(x => (ulong)x); 550 | public static implicit operator sbyte(Json value) => (sbyte)value.Number; 551 | public static implicit operator sbyte[](Json value) => value._array.ConvertAll(x => (sbyte)x).ToArray(); 552 | public static implicit operator List(Json value) => value._array.ConvertAll(x => (sbyte)x); 553 | public static implicit operator byte(Json value) => (byte)value.Number; 554 | public static implicit operator byte[](Json value) => value._array.ConvertAll(x => (byte)x).ToArray(); 555 | public static implicit operator List(Json value) => value._array.ConvertAll(x => (byte)x); 556 | 557 | public static implicit operator Uri(Json value) => value.Uri; 558 | public static implicit operator Uri[](Json value) => value._array.ConvertAll(x => (Uri)x).ToArray(); 559 | public static implicit operator List(Json value) => value._array.ConvertAll(x => (Uri)x); 560 | public static implicit operator Guid(Json value) => value.Guid; 561 | public static implicit operator Guid[](Json value) => value._array.ConvertAll(x => (Guid)x).ToArray(); 562 | public static implicit operator List(Json value) => value._array.ConvertAll(x => (Guid)x); 563 | public static implicit operator DateTime(Json value) => value.DateTime; 564 | public static implicit operator DateTime[](Json value) => value._array.ConvertAll(x => (DateTime)x).ToArray(); 565 | public static implicit operator List(Json value) => value._array.ConvertAll(x => (DateTime)x); 566 | public static implicit operator DateTimeOffset(Json value) => value.DateTimeOffset; 567 | public static implicit operator DateTimeOffset[](Json value) => value._array.ConvertAll(x => (DateTimeOffset)x).ToArray(); 568 | public static implicit operator List(Json value) => value._array.ConvertAll(x => (DateTimeOffset)x); 569 | public static implicit operator TimeSpan(Json value) => value.TimeSpan; 570 | public static implicit operator TimeSpan[](Json value) => value._array.ConvertAll(x => (TimeSpan)x).ToArray(); 571 | public static implicit operator List(Json value) => value._array.ConvertAll(x => (TimeSpan)x); 572 | public static implicit operator Color(Json value) => value.Color; 573 | public static implicit operator Color[](Json value) => value._array.ConvertAll(x => (Color)x).ToArray(); 574 | public static implicit operator List(Json value) => value._array.ConvertAll(x => (Color)x); 575 | public static implicit operator Color32(Json value) => value.Color32; 576 | public static implicit operator Color32[](Json value) => value._array.ConvertAll(x => (Color32)x).ToArray(); 577 | public static implicit operator List(Json value) => value._array.ConvertAll(x => (Color32)x); 578 | public static implicit operator Vector2(Json value) => value.Vector2; 579 | public static implicit operator Vector2[](Json value) => value._array.ConvertAll(x => (Vector2)x).ToArray(); 580 | public static implicit operator List(Json value) => value._array.ConvertAll(x => (Vector2)x); 581 | public static implicit operator Vector3(Json value) => value.Vector3; 582 | public static implicit operator Vector3[](Json value) => value._array.ConvertAll(x => (Vector3)x).ToArray(); 583 | public static implicit operator List(Json value) => value._array.ConvertAll(x => (Vector3)x); 584 | public static implicit operator Vector4(Json value) => value.Vector4; 585 | public static implicit operator Vector4[](Json value) => value._array.ConvertAll(x => (Vector4)x).ToArray(); 586 | public static implicit operator List(Json value) => value._array.ConvertAll(x => (Vector4)x); 587 | public static implicit operator Quaternion(Json value) => value.Quaternion; 588 | public static implicit operator Quaternion[](Json value) => value._array.ConvertAll(x => (Quaternion)x).ToArray(); 589 | public static implicit operator List(Json value) => value._array.ConvertAll(x => (Quaternion)x); 590 | public static implicit operator Bounds(Json value) => value.Bounds; 591 | public static implicit operator Bounds[](Json value) => value._array.ConvertAll(x => (Bounds)x).ToArray(); 592 | public static implicit operator List(Json value) => value._array.ConvertAll(x => (Bounds)x); 593 | public static implicit operator Rect(Json value) => value.Rect; 594 | public static implicit operator Rect[](Json value) => value._array.ConvertAll(x => (Rect)x).ToArray(); 595 | public static implicit operator List(Json value) => value._array.ConvertAll(x => (Rect)x); 596 | 597 | #endregion 598 | 599 | #region Serialization 600 | public string Serialize() 601 | { 602 | return JsonSerialization.Serialize(this); 603 | } 604 | 605 | public static Json Deserialize(string json) 606 | { 607 | return JsonSerialization.Deserialize(json); 608 | } 609 | 610 | public void Write(StringWriter writer, bool includeTypeInfo = false) 611 | { 612 | if (includeTypeInfo) 613 | { 614 | writer.Write("{"); 615 | writer.Write($"\"JsonType\": \"{JsonType}\", \"DataType\": \"{DataType}\", \"Value\": "); 616 | } 617 | switch (JsonType) 618 | { 619 | case JsonTypes.Undefined: 620 | case JsonTypes.Null: 621 | writer.Write("null"); 622 | break; 623 | case JsonTypes.String: 624 | writer.Write("\""); 625 | writer.Write(_string); 626 | writer.Write("\""); 627 | break; 628 | case JsonTypes.Boolean: 629 | writer.Write(_bool ? "true" : "false"); 630 | break; 631 | case JsonTypes.Number: 632 | writer.Write(_number); 633 | break; 634 | case JsonTypes.Array: 635 | writer.Write("["); 636 | int arrayIndex = 0; 637 | int arrayCount = _array.Count - 1; 638 | foreach (Json item in _array) 639 | { 640 | item.Write(writer, includeTypeInfo); 641 | if (arrayIndex < arrayCount) writer.Write(", "); 642 | arrayIndex++; 643 | } 644 | writer.Write("]"); 645 | break; 646 | case JsonTypes.Object: 647 | writer.Write("{"); 648 | if (DataType == DataTypes.Container) 649 | { 650 | int containerIndex = 0; 651 | int containerCount = _container.Count - 1; 652 | foreach (KeyValuePair kvp in _container) 653 | { 654 | writer.Write($"\"{kvp.Key}\": "); 655 | kvp.Value.Write(writer, includeTypeInfo); 656 | if (containerIndex < containerCount) writer.Write(", "); 657 | containerIndex++; 658 | } 659 | } 660 | else 661 | { 662 | int containerIndex = 0; 663 | int containerCount = _container.Count - 1; 664 | foreach (KeyValuePair kvp in _container) 665 | { 666 | writer.Write($"\"{kvp.Key}\": {kvp.Value}"); 667 | if (containerIndex < containerCount) writer.Write(", "); 668 | containerIndex++; 669 | } 670 | } 671 | writer.Write("}"); 672 | break; 673 | default: 674 | throw new ArgumentOutOfRangeException(); 675 | } 676 | 677 | if (includeTypeInfo) 678 | { 679 | writer.Write("}"); 680 | } 681 | } 682 | 683 | public static Json FromSerialization(Json jsonType, Json dataType, Json value) 684 | { 685 | value.JsonType = (JsonTypes) Enum.Parse(typeof(JsonTypes), jsonType); 686 | value.DataType = (DataTypes) Enum.Parse(typeof(DataTypes), dataType); 687 | return value; 688 | } 689 | 690 | #endregion 691 | } 692 | } --------------------------------------------------------------------------------