├── .github └── FUNDING.yml ├── .gitignore ├── LICENSE ├── README.md ├── examples └── testbed │ ├── Testbed.dpr │ ├── Testbed.dproj │ ├── Testbed.dsv │ ├── Testbed.res │ ├── Testbed_Icon.ico │ └── UTestbed.pas ├── media ├── delphi.png └── easyjson.png └── src └── EasyJson.pas /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: tinyBigGAMES # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 12 | polar: # Replace with a single Polar username 13 | buy_me_a_coffee: # Replace with a single Buy Me a Coffee username 14 | thanks_dev: # Replace with a single thanks.dev username 15 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Uncomment these types if you want even more clean repository. But be careful. 2 | # It can make harm to an existing project source. Read explanations below. 3 | # 4 | # Resource files are binaries containing manifest, project icon and version info. 5 | # They can not be viewed as text or compared by diff-tools. Consider replacing them with .rc files. 6 | #*.res 7 | # 8 | # Type library file (binary). In old Delphi versions it should be stored. 9 | # Since Delphi 2009 it is produced from .ridl file and can safely be ignored. 10 | #*.tlb 11 | # 12 | # Diagram Portfolio file. Used by the diagram editor up to Delphi 7. 13 | # Uncomment this if you are not using diagrams or use newer Delphi version. 14 | #*.ddp 15 | # 16 | # Visual LiveBindings file. Added in Delphi XE2. 17 | # Uncomment this if you are not using LiveBindings Designer. 18 | #*.vlb 19 | # 20 | # Deployment Manager configuration file for your project. Added in Delphi XE2. 21 | # Uncomment this if it is not mobile development and you do not use remote debug feature. 22 | #*.deployproj 23 | # 24 | # C++ object files produced when C/C++ Output file generation is configured. 25 | # Uncomment this if you are not using external objects (zlib library for example). 26 | #*.obj 27 | # 28 | 29 | # Default Delphi compiler directories 30 | # Content of this directories are generated with each Compile/Construct of a project. 31 | # Most of the time, files here have not there place in a code repository. 32 | #Win32/ 33 | #Win64/ 34 | #OSX64/ 35 | #OSXARM64/ 36 | #Android/ 37 | #Android64/ 38 | #iOSDevice64/ 39 | #Linux64/ 40 | 41 | # Delphi compiler-generated binaries (safe to delete) 42 | *.exe 43 | *.dll 44 | *.bpl 45 | *.bpi 46 | *.dcp 47 | *.so 48 | *.apk 49 | *.drc 50 | *.map 51 | *.dres 52 | *.rsm 53 | *.tds 54 | *.dcu 55 | *.lib 56 | *.a 57 | *.o 58 | *.ocx 59 | 60 | # Delphi autogenerated files (duplicated info) 61 | *.cfg 62 | *.hpp 63 | *Resource.rc 64 | 65 | # Delphi local files (user-specific info) 66 | *.local 67 | *.identcache 68 | *.projdata 69 | *.tvsconfig 70 | *.dsk 71 | 72 | # Delphi history and backups 73 | __history/ 74 | __recovery/ 75 | *.~* 76 | 77 | # Castalia statistics file (since XE7 Castalia is distributed with Delphi) 78 | *.stat 79 | 80 | # Boss dependency manager vendor folder https://github.com/HashLoad/boss 81 | modules/ 82 | bin/data.json 83 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2025-present, tinyBigGAMES LLC 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its 16 | contributors may be used to endorse or promote products derived from 17 | this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ![EasyJson](media/easyjson.png) 2 | [![Chat on Discord](https://img.shields.io/discord/754884471324672040?style=for-the-badge)](https://discord.gg/tPWjMwK) [![Follow on Bluesky](https://img.shields.io/badge/Bluesky-tinyBigGAMES-blue?style=for-the-badge&logo=bluesky)](https://bsky.app/profile/tinybiggames.com) 3 | 4 | ## 🚀 Overview 5 | 6 | **`TEasyJson`** is a powerful and intuitive Delphi class that simplifies JSON manipulation. Designed with a fluent interface, it enables developers to seamlessly create, modify, and traverse JSON objects and arrays using method chaining. Whether handling simple key-value pairs or deeply nested structures, `TEasyJson` ensures efficiency, readability, and flexibility. 7 | 8 | ## ✨ Features 9 | 10 | - 🚀 Fluent interface for effortless JSON manipulation 11 | - 📂 Supports both JSON objects and arrays 12 | - 🔗 Chainable methods for concise and readable code 13 | - 🏗️ Easily constructs and modifies nested JSON structures 14 | - 🎨 Provides formatted JSON output for better readability 15 | - ⚡ Optimized for performance and efficiency 16 | 17 | ## 📥 Installation 18 | 19 | Getting started with `TEasyJson` is quick and easy: 20 | 21 | 1. **Copy** `TEasyJson.pas` into your project. 22 | 2. **Add** `TEasyJson` to your `uses` clause. 23 | 3. **Start Coding!** Enjoy simplified JSON handling with method chaining. 24 | 25 | ## 🛠️ Usage 26 | 27 | ### 🔹 Creating a JSON Object 28 | 29 | ```delphi 30 | var EJ: TEasyJson; 31 | begin 32 | EJ := TEasyJson.Create; 33 | EJ.Put('name', 'Alice') 34 | .Put('age', 25) 35 | .AddArray('hobbies') 36 | .Put(0, 'Reading') 37 | .Put(1, 'Cycling'); 38 | 39 | WriteLn(EJ.Format()); 40 | end; 41 | ``` 42 | 43 | #### 🏷️ Output: 44 | ```json 45 | { 46 | "name": "Alice", 47 | "age": 25, 48 | "hobbies": [ 49 | "Reading", 50 | "Cycling" 51 | ] 52 | } 53 | ``` 54 | 55 | ### 🔹 Creating a JSON Object from a String 56 | ```delphi 57 | var EJ: TEasyJson; 58 | begin 59 | EJ := TEasyJson.Create('{"name":"John","age":30}'); 60 | WriteLn(EJ.Format()); 61 | end; 62 | ``` 63 | 64 | ### 🔹 Adding and Modifying Values 65 | ```delphi 66 | EJ.Put('email', 'alice@example.com'); 67 | EJ.Put('age', 26); // Updates existing key 68 | ``` 69 | 70 | ### 🔹 Working with JSON Arrays 71 | ```delphi 72 | var EJ: TEasyJson; 73 | begin 74 | EJ := TEasyJson.Create; 75 | EJ.AddArray('numbers') 76 | .Put(0, 10) 77 | .Put(1, 20) 78 | .Put(2, 30); 79 | 80 | WriteLn(EJ.Format()); 81 | end; 82 | ``` 83 | 84 | ### 🔹 Nesting JSON Objects 85 | ```delphi 86 | EJ.AddObject('address', 87 | function(E: TEasyJson): TEasyJson 88 | begin 89 | Result := E.Put('city', 'New York') 90 | .Put('zip', '10001'); 91 | end); 92 | ``` 93 | 94 | ### 🔹 Accessing JSON Elements 95 | ```delphi 96 | WriteLn(EJ['name'].AsString); // Alice 97 | WriteLn(EJ['age'].AsInteger); // 26 98 | WriteLn(EJ['hobbies'][1].AsString); // Cycling 99 | ``` 100 | 101 | ## 📖 API Reference 102 | 103 | The `TEasyJson` class provides a robust set of methods and properties for seamless JSON manipulation. 104 | 105 | ### 🔹 Constructors 106 | - `Create()` – Creates an empty JSON object. 107 | - `Create(const AJson: string)` – Parses a JSON string. 108 | - `Create(const AJsonValue: TJSONValue)` – Wraps an existing JSON value. 109 | 110 | ### 🔹 Methods 111 | - `Put(AKey: string; AValue: Variant): TEasyJson` – Adds or updates a key. 112 | - `Put(AIndex: Integer; AValue: Variant): TEasyJson` – Sets an array element. 113 | - `Add(AKey: string; AValue: Variant): TEasyJson` – Adds a new key-value pair. 114 | - `AddArray(AKey: string): TEasyJson` – Adds an empty array. 115 | - `AddObject(AKey: string; AFunc: TFunc): TEasyJson` – Adds a nested object. 116 | - `ToString(): string` – Returns a compact JSON string. 117 | - `Format(): string` – Returns formatted JSON. 118 | - `Count(): Integer` – Returns the number of elements. 119 | - `AsString(): string` – Converts a JSON value to a string. 120 | - `AsInt32r(): Int32` – Converts a JSON value to an int32. 121 | - `AsFloat(): Double` – Converts a JSON value to a float. 122 | - `AsBoolean(): Boolean` – Converts a JSON value to a boolean. 123 | 124 | ### 🔹 Properties 125 | - `Items[AKeyOrIndex: Variant]: TEasyJson` – Accesses elements by key or index. 126 | 127 | See `EasyJson.pas` for the full documented API. 128 | 129 | ## 💬 Support & Resources 130 | 131 | - 🐞 **Report Issues:** [GitHub Issue Tracker](https://github.com/tinyBigGAMES/EasyJson/issues) 132 | - 💬 **Join the Community:** [Forum](https://github.com/tinyBigGAMES/EasyJson/discussions) | [Discord](https://discord.gg/tPWjMwK) 133 | - 📚 **Learn Delphi:** [Learn Delphi](https://learndelphi.org) 134 | 135 | ## 🤝 Contributing 136 | 137 | We welcome contributions to **EasyJson**! 🚀 138 | 139 | ### 💡 Ways to Contribute: 140 | - 🐛 **Report Bugs** – Help improve `TEasyJson` by submitting issues. 141 | - ✨ **Suggest Features** – Share ideas to enhance its functionality. 142 | - 🔧 **Submit Pull Requests** – Improve the codebase and add features. 143 | 144 | ### 🏆 Contributors 145 | 146 | 147 | 148 | 149 | 150 | ## 📜 License 151 | 152 | **EasyJson** is distributed under the **BSD-3-Clause License**, allowing redistribution and modification in both source and binary forms. 153 | See the [LICENSE](https://github.com/tinyBigGAMES/EasyJson?tab=BSD-3-Clause-1-ov-file#BSD-3-Clause-1-ov-file) for details. 154 | 155 | ## 💖 Support & Sponsorship 156 | 157 | Your support keeps **EasyJson** evolving! If you find this library useful, please consider [sponsoring the project](https://github.com/sponsors/tinyBigGAMES). Every contribution helps drive future enhancements and innovations. 158 | 159 | ### Other ways to support: 160 | - ⭐ **Star the repo** – Show your appreciation. 161 | - 📢 **Share with your network** – Spread the word. 162 | - 🐛 **Report bugs** – Help improve `TEasyJson`. 163 | - 🔧 **Submit fixes** – Contribute by fixing issues. 164 | - 💡 **Suggest features** – Help shape its future. 165 | 166 | 🚀 Every contribution makes a difference – thank you for being part of the journey! 167 | 168 | --- 169 | 170 | 🔥 *EasyJson – Effortless JSON Handling for Delphi with Fluent Simplicity.* 171 | 172 |

173 | Delphi 174 |

175 |
Made with ❤️ in Delphi
176 | 177 | -------------------------------------------------------------------------------- /examples/testbed/Testbed.dpr: -------------------------------------------------------------------------------- 1 | {=============================================================================== 2 | ___ _ 3 | | __|__ _ ____ _ _ | |___ ___ _ _ ™ 4 | | _|/ _` (_-< || | || (_- 2 | 3 | {3AADAF03-CABC-4664-AFD1-2F61832541CE} 4 | 20.3 5 | None 6 | True 7 | Release 8 | Win64 9 | Testbed 10 | 2 11 | Console 12 | Testbed.dpr 13 | 14 | 15 | true 16 | 17 | 18 | true 19 | Base 20 | true 21 | 22 | 23 | true 24 | Base 25 | true 26 | 27 | 28 | true 29 | Base 30 | true 31 | 32 | 33 | true 34 | Cfg_1 35 | true 36 | true 37 | 38 | 39 | true 40 | Cfg_1 41 | true 42 | true 43 | 44 | 45 | true 46 | Base 47 | true 48 | 49 | 50 | true 51 | Cfg_2 52 | true 53 | true 54 | 55 | 56 | .\$(Platform)\$(Config) 57 | .\$(Platform)\$(Config) 58 | false 59 | false 60 | false 61 | false 62 | false 63 | System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace) 64 | Testbed 65 | 66 | 67 | vclwinx;DataSnapServer;fmx;emshosting;vclie;DbxCommonDriver;bindengine;IndyIPCommon;VCLRESTComponents;DBXMSSQLDriver;FireDACCommonODBC;emsclient;FireDACCommonDriver;appanalytics;IndyProtocols;vclx;Skia.Package.RTL;IndyIPClient;dbxcds;vcledge;bindcompvclwinx;emsedge;bindcompfmx;DBXFirebirdDriver;inetdb;FireDACSqliteDriver;DbxClientDriver;FireDACASADriver;JclVcl;soapmidas;vclactnband;fmxFireDAC;dbexpress;Jcl;FireDACInfxDriver;DBXMySQLDriver;VclSmp;inet;DataSnapCommon;vcltouch;fmxase;DBXOdbcDriver;dbrtl;FireDACDBXDriver;Skia.Package.FMX;FireDACOracleDriver;fmxdae;FireDACMSAccDriver;CustomIPTransport;FireDACMSSQLDriver;DataSnapIndy10ServerTransport;JclDeveloperTools;DataSnapConnectors;vcldsnap;DBXInterBaseDriver;FireDACMongoDBDriver;IndySystem;FireDACTDataDriver;Skia.Package.VCL;vcldb;JclContainers;vclFireDAC;bindcomp;FireDACCommon;DataSnapServerMidas;FireDACODBCDriver;emsserverresource;inetstn;IndyCore;RESTBackendComponents;bindcompdbx;rtl;FireDACMySQLDriver;FireDACADSDriver;RESTComponents;DBXSqliteDriver;vcl;IndyIPServer;dsnapxml;dsnapcon;DataSnapClient;DataSnapProviderClient;adortl;DBXSybaseASEDriver;DBXDb2Driver;vclimg;DataSnapFireDAC;emsclientfiredac;FireDACPgDriver;FireDAC;FireDACDSDriver;inetdbxpress;xmlrtl;tethering;bindcompvcl;dsnap;CloudService;DBXSybaseASADriver;DBXOracleDriver;FireDACDb2Driver;DBXInformixDriver;fmxobj;bindcompvclsmp;DataSnapNativeClient;DatasnapConnectorsFreePascal;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage) 68 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) 69 | Debug 70 | CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= 71 | 1033 72 | true 73 | $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png 74 | $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png 75 | 76 | 77 | vclwinx;DataSnapServer;fmx;emshosting;vclie;DbxCommonDriver;bindengine;IndyIPCommon;VCLRESTComponents;DBXMSSQLDriver;FireDACCommonODBC;emsclient;FireDACCommonDriver;appanalytics;IndyProtocols;vclx;IndyIPClient;dbxcds;vcledge;bindcompvclwinx;emsedge;bindcompfmx;DBXFirebirdDriver;inetdb;FireDACSqliteDriver;DbxClientDriver;FireDACASADriver;soapmidas;vclactnband;fmxFireDAC;dbexpress;FireDACInfxDriver;DBXMySQLDriver;VclSmp;inet;DataSnapCommon;vcltouch;fmxase;DBXOdbcDriver;dbrtl;FireDACDBXDriver;FireDACOracleDriver;fmxdae;FireDACMSAccDriver;CustomIPTransport;FireDACMSSQLDriver;DataSnapIndy10ServerTransport;DataSnapConnectors;vcldsnap;DBXInterBaseDriver;FireDACMongoDBDriver;IndySystem;FireDACTDataDriver;Skia.Package.VCL;vcldb;vclFireDAC;bindcomp;FireDACCommon;DataSnapServerMidas;FireDACODBCDriver;emsserverresource;inetstn;IndyCore;RESTBackendComponents;bindcompdbx;rtl;FireDACMySQLDriver;FireDACADSDriver;RESTComponents;DBXSqliteDriver;vcl;IndyIPServer;dsnapxml;dsnapcon;DataSnapClient;DataSnapProviderClient;adortl;DBXSybaseASEDriver;DBXDb2Driver;vclimg;DataSnapFireDAC;emsclientfiredac;FireDACPgDriver;FireDAC;FireDACDSDriver;inetdbxpress;xmlrtl;tethering;bindcompvcl;dsnap;CloudService;DBXSybaseASADriver;DBXOracleDriver;FireDACDb2Driver;DBXInformixDriver;fmxobj;bindcompvclsmp;DataSnapNativeClient;DatasnapConnectorsFreePascal;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage) 78 | true 79 | $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png 80 | $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png 81 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace) 82 | Debug 83 | CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= 84 | 1033 85 | ..\..\bin 86 | $(BDS)\bin\default_app.manifest 87 | PerMonitorV2 88 | Testbed_Icon.ico 89 | 90 | 91 | DEBUG;$(DCC_Define) 92 | true 93 | false 94 | true 95 | true 96 | true 97 | true 98 | true 99 | 100 | 101 | false 102 | 103 | 104 | 1033 105 | 106 | 107 | false 108 | RELEASE;$(DCC_Define) 109 | 0 110 | 0 111 | 112 | 113 | 1033 114 | 115 | 116 | 117 | MainSource 118 | 119 | 120 | 121 | 122 | Base 123 | 124 | 125 | Cfg_1 126 | Base 127 | 128 | 129 | Cfg_2 130 | Base 131 | 132 | 133 | 134 | Delphi.Personality.12 135 | Application 136 | 137 | 138 | 139 | Testbed.dpr 140 | 141 | 142 | Embarcadero C++Builder Office 2000 Servers Package 143 | Embarcadero C++Builder Office XP Servers Package 144 | Microsoft Office 2000 Sample Automation Server Wrapper Components 145 | Microsoft Office XP Sample Automation Server Wrapper Components 146 | 147 | 148 | 149 | 150 | 151 | true 152 | 153 | 154 | 155 | 156 | true 157 | 158 | 159 | 160 | 161 | true 162 | 163 | 164 | 165 | 166 | Testbed.exe 167 | true 168 | 169 | 170 | 171 | 172 | Testbed.rsm 173 | true 174 | 175 | 176 | 177 | 178 | Testbed.exe 179 | true 180 | 181 | 182 | 183 | 184 | 1 185 | 186 | 187 | Contents\MacOS 188 | 1 189 | 190 | 191 | 0 192 | 193 | 194 | 195 | 196 | res\xml 197 | 1 198 | 199 | 200 | res\xml 201 | 1 202 | 203 | 204 | 205 | 206 | library\lib\armeabi 207 | 1 208 | 209 | 210 | library\lib\armeabi 211 | 1 212 | 213 | 214 | 215 | 216 | library\lib\armeabi-v7a 217 | 1 218 | 219 | 220 | 221 | 222 | library\lib\mips 223 | 1 224 | 225 | 226 | library\lib\mips 227 | 1 228 | 229 | 230 | 231 | 232 | library\lib\armeabi-v7a 233 | 1 234 | 235 | 236 | library\lib\arm64-v8a 237 | 1 238 | 239 | 240 | 241 | 242 | library\lib\armeabi-v7a 243 | 1 244 | 245 | 246 | 247 | 248 | res\drawable 249 | 1 250 | 251 | 252 | res\drawable 253 | 1 254 | 255 | 256 | 257 | 258 | res\drawable-anydpi-v21 259 | 1 260 | 261 | 262 | res\drawable-anydpi-v21 263 | 1 264 | 265 | 266 | 267 | 268 | res\values 269 | 1 270 | 271 | 272 | res\values 273 | 1 274 | 275 | 276 | 277 | 278 | res\values-v21 279 | 1 280 | 281 | 282 | res\values-v21 283 | 1 284 | 285 | 286 | 287 | 288 | res\values-v31 289 | 1 290 | 291 | 292 | res\values-v31 293 | 1 294 | 295 | 296 | 297 | 298 | res\values-v35 299 | 1 300 | 301 | 302 | res\values-v35 303 | 1 304 | 305 | 306 | 307 | 308 | res\drawable-anydpi-v26 309 | 1 310 | 311 | 312 | res\drawable-anydpi-v26 313 | 1 314 | 315 | 316 | 317 | 318 | res\drawable 319 | 1 320 | 321 | 322 | res\drawable 323 | 1 324 | 325 | 326 | 327 | 328 | res\drawable 329 | 1 330 | 331 | 332 | res\drawable 333 | 1 334 | 335 | 336 | 337 | 338 | res\drawable 339 | 1 340 | 341 | 342 | res\drawable 343 | 1 344 | 345 | 346 | 347 | 348 | res\drawable-anydpi-v33 349 | 1 350 | 351 | 352 | res\drawable-anydpi-v33 353 | 1 354 | 355 | 356 | 357 | 358 | res\values 359 | 1 360 | 361 | 362 | res\values 363 | 1 364 | 365 | 366 | 367 | 368 | res\values-night-v21 369 | 1 370 | 371 | 372 | res\values-night-v21 373 | 1 374 | 375 | 376 | 377 | 378 | res\drawable 379 | 1 380 | 381 | 382 | res\drawable 383 | 1 384 | 385 | 386 | 387 | 388 | res\drawable-xxhdpi 389 | 1 390 | 391 | 392 | res\drawable-xxhdpi 393 | 1 394 | 395 | 396 | 397 | 398 | res\drawable-xxxhdpi 399 | 1 400 | 401 | 402 | res\drawable-xxxhdpi 403 | 1 404 | 405 | 406 | 407 | 408 | res\drawable-ldpi 409 | 1 410 | 411 | 412 | res\drawable-ldpi 413 | 1 414 | 415 | 416 | 417 | 418 | res\drawable-mdpi 419 | 1 420 | 421 | 422 | res\drawable-mdpi 423 | 1 424 | 425 | 426 | 427 | 428 | res\drawable-hdpi 429 | 1 430 | 431 | 432 | res\drawable-hdpi 433 | 1 434 | 435 | 436 | 437 | 438 | res\drawable-xhdpi 439 | 1 440 | 441 | 442 | res\drawable-xhdpi 443 | 1 444 | 445 | 446 | 447 | 448 | res\drawable-mdpi 449 | 1 450 | 451 | 452 | res\drawable-mdpi 453 | 1 454 | 455 | 456 | 457 | 458 | res\drawable-hdpi 459 | 1 460 | 461 | 462 | res\drawable-hdpi 463 | 1 464 | 465 | 466 | 467 | 468 | res\drawable-xhdpi 469 | 1 470 | 471 | 472 | res\drawable-xhdpi 473 | 1 474 | 475 | 476 | 477 | 478 | res\drawable-xxhdpi 479 | 1 480 | 481 | 482 | res\drawable-xxhdpi 483 | 1 484 | 485 | 486 | 487 | 488 | res\drawable-xxxhdpi 489 | 1 490 | 491 | 492 | res\drawable-xxxhdpi 493 | 1 494 | 495 | 496 | 497 | 498 | res\drawable-small 499 | 1 500 | 501 | 502 | res\drawable-small 503 | 1 504 | 505 | 506 | 507 | 508 | res\drawable-normal 509 | 1 510 | 511 | 512 | res\drawable-normal 513 | 1 514 | 515 | 516 | 517 | 518 | res\drawable-large 519 | 1 520 | 521 | 522 | res\drawable-large 523 | 1 524 | 525 | 526 | 527 | 528 | res\drawable-xlarge 529 | 1 530 | 531 | 532 | res\drawable-xlarge 533 | 1 534 | 535 | 536 | 537 | 538 | res\values 539 | 1 540 | 541 | 542 | res\values 543 | 1 544 | 545 | 546 | 547 | 548 | res\drawable-anydpi-v24 549 | 1 550 | 551 | 552 | res\drawable-anydpi-v24 553 | 1 554 | 555 | 556 | 557 | 558 | res\drawable 559 | 1 560 | 561 | 562 | res\drawable 563 | 1 564 | 565 | 566 | 567 | 568 | res\drawable-night-anydpi-v21 569 | 1 570 | 571 | 572 | res\drawable-night-anydpi-v21 573 | 1 574 | 575 | 576 | 577 | 578 | res\drawable-anydpi-v31 579 | 1 580 | 581 | 582 | res\drawable-anydpi-v31 583 | 1 584 | 585 | 586 | 587 | 588 | res\drawable-night-anydpi-v31 589 | 1 590 | 591 | 592 | res\drawable-night-anydpi-v31 593 | 1 594 | 595 | 596 | 597 | 598 | 1 599 | 600 | 601 | Contents\MacOS 602 | 1 603 | 604 | 605 | 0 606 | 607 | 608 | 609 | 610 | Contents\MacOS 611 | 1 612 | .framework 613 | 614 | 615 | Contents\MacOS 616 | 1 617 | .framework 618 | 619 | 620 | Contents\MacOS 621 | 1 622 | .framework 623 | 624 | 625 | 0 626 | 627 | 628 | 629 | 630 | 1 631 | .dylib 632 | 633 | 634 | 1 635 | .dylib 636 | 637 | 638 | 1 639 | .dylib 640 | 641 | 642 | Contents\MacOS 643 | 1 644 | .dylib 645 | 646 | 647 | Contents\MacOS 648 | 1 649 | .dylib 650 | 651 | 652 | Contents\MacOS 653 | 1 654 | .dylib 655 | 656 | 657 | 0 658 | .dll;.bpl 659 | 660 | 661 | 662 | 663 | 1 664 | .dylib 665 | 666 | 667 | 1 668 | .dylib 669 | 670 | 671 | 1 672 | .dylib 673 | 674 | 675 | Contents\MacOS 676 | 1 677 | .dylib 678 | 679 | 680 | Contents\MacOS 681 | 1 682 | .dylib 683 | 684 | 685 | Contents\MacOS 686 | 1 687 | .dylib 688 | 689 | 690 | 0 691 | .bpl 692 | 693 | 694 | 695 | 696 | 0 697 | 698 | 699 | 0 700 | 701 | 702 | 0 703 | 704 | 705 | 0 706 | 707 | 708 | 0 709 | 710 | 711 | Contents\Resources\StartUp\ 712 | 0 713 | 714 | 715 | Contents\Resources\StartUp\ 716 | 0 717 | 718 | 719 | Contents\Resources\StartUp\ 720 | 0 721 | 722 | 723 | 0 724 | 725 | 726 | 727 | 728 | 1 729 | 730 | 731 | 1 732 | 733 | 734 | 735 | 736 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 737 | 1 738 | 739 | 740 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 741 | 1 742 | 743 | 744 | 745 | 746 | ..\ 747 | 1 748 | 749 | 750 | ..\ 751 | 1 752 | 753 | 754 | ..\ 755 | 1 756 | 757 | 758 | 759 | 760 | Contents 761 | 1 762 | 763 | 764 | Contents 765 | 1 766 | 767 | 768 | Contents 769 | 1 770 | 771 | 772 | 773 | 774 | Contents\Resources 775 | 1 776 | 777 | 778 | Contents\Resources 779 | 1 780 | 781 | 782 | Contents\Resources 783 | 1 784 | 785 | 786 | 787 | 788 | library\lib\armeabi-v7a 789 | 1 790 | 791 | 792 | library\lib\arm64-v8a 793 | 1 794 | 795 | 796 | 1 797 | 798 | 799 | 1 800 | 801 | 802 | 1 803 | 804 | 805 | 1 806 | 807 | 808 | Contents\MacOS 809 | 1 810 | 811 | 812 | Contents\MacOS 813 | 1 814 | 815 | 816 | Contents\MacOS 817 | 1 818 | 819 | 820 | 0 821 | 822 | 823 | 824 | 825 | library\lib\armeabi-v7a 826 | 1 827 | 828 | 829 | 830 | 831 | 1 832 | 833 | 834 | 1 835 | 836 | 837 | 1 838 | 839 | 840 | 841 | 842 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 843 | 1 844 | 845 | 846 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 847 | 1 848 | 849 | 850 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 851 | 1 852 | 853 | 854 | 855 | 856 | ..\ 857 | 1 858 | 859 | 860 | ..\ 861 | 1 862 | 863 | 864 | ..\ 865 | 1 866 | 867 | 868 | 869 | 870 | 1 871 | 872 | 873 | 1 874 | 875 | 876 | 1 877 | 878 | 879 | 880 | 881 | ..\$(PROJECTNAME).launchscreen 882 | 64 883 | 884 | 885 | ..\$(PROJECTNAME).launchscreen 886 | 64 887 | 888 | 889 | 890 | 891 | 1 892 | 893 | 894 | 1 895 | 896 | 897 | 1 898 | 899 | 900 | 901 | 902 | Assets 903 | 1 904 | 905 | 906 | Assets 907 | 1 908 | 909 | 910 | 911 | 912 | Assets 913 | 1 914 | 915 | 916 | Assets 917 | 1 918 | 919 | 920 | 921 | 922 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 923 | 1 924 | 925 | 926 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 927 | 1 928 | 929 | 930 | 931 | 932 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 933 | 1 934 | 935 | 936 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 937 | 1 938 | 939 | 940 | 941 | 942 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 943 | 1 944 | 945 | 946 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 947 | 1 948 | 949 | 950 | 951 | 952 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 953 | 1 954 | 955 | 956 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 957 | 1 958 | 959 | 960 | 961 | 962 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 963 | 1 964 | 965 | 966 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 967 | 1 968 | 969 | 970 | 971 | 972 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 973 | 1 974 | 975 | 976 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 977 | 1 978 | 979 | 980 | 981 | 982 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 983 | 1 984 | 985 | 986 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 987 | 1 988 | 989 | 990 | 991 | 992 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 993 | 1 994 | 995 | 996 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 997 | 1 998 | 999 | 1000 | 1001 | 1002 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1003 | 1 1004 | 1005 | 1006 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1007 | 1 1008 | 1009 | 1010 | 1011 | 1012 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1013 | 1 1014 | 1015 | 1016 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1017 | 1 1018 | 1019 | 1020 | 1021 | 1022 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1023 | 1 1024 | 1025 | 1026 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1027 | 1 1028 | 1029 | 1030 | 1031 | 1032 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1033 | 1 1034 | 1035 | 1036 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1037 | 1 1038 | 1039 | 1040 | 1041 | 1042 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1043 | 1 1044 | 1045 | 1046 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1047 | 1 1048 | 1049 | 1050 | 1051 | 1052 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1053 | 1 1054 | 1055 | 1056 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1057 | 1 1058 | 1059 | 1060 | 1061 | 1062 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1063 | 1 1064 | 1065 | 1066 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1067 | 1 1068 | 1069 | 1070 | 1071 | 1072 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1073 | 1 1074 | 1075 | 1076 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1077 | 1 1078 | 1079 | 1080 | 1081 | 1082 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1083 | 1 1084 | 1085 | 1086 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1087 | 1 1088 | 1089 | 1090 | 1091 | 1092 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1093 | 1 1094 | 1095 | 1096 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1097 | 1 1098 | 1099 | 1100 | 1101 | 1102 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1103 | 1 1104 | 1105 | 1106 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1107 | 1 1108 | 1109 | 1110 | 1111 | 1112 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1113 | 1 1114 | 1115 | 1116 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1117 | 1 1118 | 1119 | 1120 | 1121 | 1122 | 1123 | 1124 | 1125 | 1126 | 1127 | 1128 | 1129 | 1130 | 1131 | 1132 | 1133 | 1134 | False 1135 | True 1136 | 1137 | 1138 | 12 1139 | 1140 | 1141 | 1142 | 1143 | 1144 | -------------------------------------------------------------------------------- /examples/testbed/Testbed.dsv: -------------------------------------------------------------------------------- 1 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXHNyY1xFYXN5SnNvbi5wYXM=] 2 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\src\EasyJson.pas 3 | CursorX=1 4 | CursorY=2008 5 | TopLine=1992 6 | LeftCol=1 7 | Elisions= 8 | Bookmarks= 9 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\src\EasyJson.pas 10 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 11 | c3RiZWQucGFz] 12 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 13 | CursorX=1 14 | CursorY=17 15 | TopLine=1 16 | LeftCol=1 17 | Elisions= 18 | Bookmarks= 19 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 20 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVGVz 21 | dGJlZC5kcHI=] 22 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\Testbed.dpr 23 | CursorX=1 24 | CursorY=17 25 | TopLine=1 26 | LeftCol=1 27 | Elisions= 28 | Bookmarks= 29 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\Testbed.dpr 30 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 31 | c3RiZWQucGFz] 32 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 33 | CursorX=1 34 | CursorY=136 35 | TopLine=1 36 | LeftCol=1 37 | Elisions= 38 | Bookmarks= 39 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 40 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 41 | c3RiZWQucGFz] 42 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 43 | CursorX=1 44 | CursorY=136 45 | TopLine=130 46 | LeftCol=1 47 | Elisions= 48 | Bookmarks= 49 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 50 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVGVz 51 | dGJlZC5kcHI=] 52 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\Testbed.dpr 53 | CursorX=1 54 | CursorY=17 55 | TopLine=1 56 | LeftCol=1 57 | Elisions= 58 | Bookmarks= 59 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\Testbed.dpr 60 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVGVz 61 | dGJlZC5kcHI=] 62 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\Testbed.dpr 63 | CursorX=1 64 | CursorY=17 65 | TopLine=1 66 | LeftCol=1 67 | Elisions= 68 | Bookmarks= 69 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\Testbed.dpr 70 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 71 | c3RiZWQucGFz] 72 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 73 | CursorX=1 74 | CursorY=190 75 | TopLine=163 76 | LeftCol=1 77 | Elisions= 78 | Bookmarks= 79 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 80 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 81 | c3RiZWQucGFz] 82 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 83 | CursorX=13 84 | CursorY=212 85 | TopLine=157 86 | LeftCol=1 87 | Elisions= 88 | Bookmarks= 89 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 90 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 91 | c3RiZWQucGFz] 92 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 93 | CursorX=111 94 | CursorY=203 95 | TopLine=184 96 | LeftCol=1 97 | Elisions= 98 | Bookmarks= 99 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 100 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 101 | c3RiZWQucGFz] 102 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 103 | CursorX=53 104 | CursorY=180 105 | TopLine=163 106 | LeftCol=1 107 | Elisions= 108 | Bookmarks= 109 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 110 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 111 | c3RiZWQucGFz] 112 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 113 | CursorX=27 114 | CursorY=183 115 | TopLine=172 116 | LeftCol=1 117 | Elisions= 118 | Bookmarks= 119 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 120 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 121 | c3RiZWQucGFz] 122 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 123 | CursorX=1 124 | CursorY=182 125 | TopLine=160 126 | LeftCol=1 127 | Elisions= 128 | Bookmarks= 129 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 130 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 131 | c3RiZWQucGFz] 132 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 133 | CursorX=10 134 | CursorY=182 135 | TopLine=160 136 | LeftCol=1 137 | Elisions= 138 | Bookmarks= 139 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 140 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 141 | c3RiZWQucGFz] 142 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 143 | CursorX=32 144 | CursorY=178 145 | TopLine=160 146 | LeftCol=1 147 | Elisions= 148 | Bookmarks= 149 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 150 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 151 | c3RiZWQucGFz] 152 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 153 | CursorX=24 154 | CursorY=188 155 | TopLine=160 156 | LeftCol=1 157 | Elisions= 158 | Bookmarks= 159 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 160 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 161 | c3RiZWQucGFz] 162 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 163 | CursorX=94 164 | CursorY=197 165 | TopLine=160 166 | LeftCol=1 167 | Elisions= 168 | Bookmarks= 169 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 170 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 171 | c3RiZWQucGFz] 172 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 173 | CursorX=1 174 | CursorY=182 175 | TopLine=160 176 | LeftCol=1 177 | Elisions= 178 | Bookmarks= 179 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 180 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 181 | c3RiZWQucGFz] 182 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 183 | CursorX=20 184 | CursorY=178 185 | TopLine=160 186 | LeftCol=1 187 | Elisions= 188 | Bookmarks= 189 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 190 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 191 | c3RiZWQucGFz] 192 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 193 | CursorX=36 194 | CursorY=179 195 | TopLine=160 196 | LeftCol=1 197 | Elisions= 198 | Bookmarks= 199 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 200 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 201 | c3RiZWQucGFz] 202 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 203 | CursorX=116 204 | CursorY=231 205 | TopLine=215 206 | LeftCol=1 207 | Elisions= 208 | Bookmarks= 209 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 210 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 211 | c3RiZWQucGFz] 212 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 213 | CursorX=1 214 | CursorY=233 215 | TopLine=233 216 | LeftCol=1 217 | Elisions= 218 | Bookmarks= 219 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 220 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 221 | c3RiZWQucGFz] 222 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 223 | CursorX=33 224 | CursorY=215 225 | TopLine=210 226 | LeftCol=1 227 | Elisions= 228 | Bookmarks= 229 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 230 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 231 | c3RiZWQucGFz] 232 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 233 | CursorX=24 234 | CursorY=235 235 | TopLine=210 236 | LeftCol=1 237 | Elisions= 238 | Bookmarks= 239 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 240 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 241 | c3RiZWQucGFz] 242 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 243 | CursorX=14 244 | CursorY=234 245 | TopLine=210 246 | LeftCol=1 247 | Elisions= 248 | Bookmarks= 249 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 250 | [ClosedView_YzpccHJvZ3JhbSBmaWxlcyAoeDg2KVxlbWJhcmNhZGVyb1xzdHVkaW9cMjMuMFxzb3VyY2VccnRs 251 | XGNvbW1vblxTeXN0ZW0uSlNPTi5wYXM=] 252 | Module=c:\program files (x86)\embarcadero\studio\23.0\source\rtl\common\System.JSON.pas 253 | CursorX=45 254 | CursorY=1574 255 | TopLine=1571 256 | LeftCol=1 257 | Elisions= 258 | Bookmarks= 259 | EditViewName=c:\program files (x86)\embarcadero\studio\23.0\source\rtl\common\System.JSON.pas 260 | [ClosedView_YzpccHJvZ3JhbSBmaWxlcyAoeDg2KVxlbWJhcmNhZGVyb1xzdHVkaW9cMjMuMFxzb3VyY2VccnRs 261 | XGNvbW1vblxTeXN0ZW0uSlNPTi5wYXM=] 262 | Module=c:\program files (x86)\embarcadero\studio\23.0\source\rtl\common\System.JSON.pas 263 | CursorX=1 264 | CursorY=3491 265 | TopLine=3463 266 | LeftCol=1 267 | Elisions= 268 | Bookmarks= 269 | EditViewName=c:\program files (x86)\embarcadero\studio\23.0\source\rtl\common\System.JSON.pas 270 | 271 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXHNyY1xFYXN5SnNvbjIucGFz] 272 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\src\EasyJson2.pas 273 | CursorX=1 274 | CursorY=17 275 | TopLine=1 276 | LeftCol=1 277 | Elisions= 278 | Bookmarks= 279 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\src\EasyJson2.pas 280 | [ClosedView_YzpccHJvZ3JhbSBmaWxlcyAoeDg2KVxlbWJhcmNhZGVyb1xzdHVkaW9cMjMuMFxzb3VyY2VccnRs 281 | XGNvbW1vblxTeXN0ZW0uSlNPTi5wYXM=] 282 | Module=c:\program files (x86)\embarcadero\studio\23.0\source\rtl\common\System.JSON.pas 283 | CursorX=45 284 | CursorY=164 285 | TopLine=136 286 | LeftCol=1 287 | Elisions= 288 | Bookmarks= 289 | EditViewName=c:\program files (x86)\embarcadero\studio\23.0\source\rtl\common\System.JSON.pas 290 | [ClosedView_YzpccHJvZ3JhbSBmaWxlcyAoeDg2KVxlbWJhcmNhZGVyb1xzdHVkaW9cMjMuMFxzb3VyY2VccnRs 291 | XGNvbW1vblxTeXN0ZW0uSlNPTi5wYXM=] 292 | Module=c:\program files (x86)\embarcadero\studio\23.0\source\rtl\common\System.JSON.pas 293 | CursorX=46 294 | CursorY=164 295 | TopLine=136 296 | LeftCol=1 297 | Elisions= 298 | Bookmarks= 299 | EditViewName=c:\program files (x86)\embarcadero\studio\23.0\source\rtl\common\System.JSON.pas 300 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 301 | c3RiZWQucGFz] 302 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 303 | CursorX=25 304 | CursorY=176 305 | TopLine=129 306 | LeftCol=1 307 | Elisions= 308 | Bookmarks= 309 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 310 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 311 | c3RiZWQucGFz] 312 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 313 | CursorX=25 314 | CursorY=176 315 | TopLine=129 316 | LeftCol=1 317 | Elisions= 318 | Bookmarks= 319 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 320 | [ClosedView_YzpccHJvZ3JhbSBmaWxlcyAoeDg2KVxlbWJhcmNhZGVyb1xzdHVkaW9cMjMuMFxzb3VyY2VccnRs 321 | XGNvbW1vblxTeXN0ZW0uSlNPTi5wYXM=] 322 | Module=c:\program files (x86)\embarcadero\studio\23.0\source\rtl\common\System.JSON.pas 323 | CursorX=46 324 | CursorY=164 325 | TopLine=127 326 | LeftCol=1 327 | Elisions= 328 | Bookmarks= 329 | EditViewName=c:\program files (x86)\embarcadero\studio\23.0\source\rtl\common\System.JSON.pas 330 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 331 | c3RiZWQucGFz] 332 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 333 | CursorX=11 334 | CursorY=23 335 | TopLine=10 336 | LeftCol=1 337 | Elisions= 338 | Bookmarks= 339 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 340 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 341 | c3RiZWQucGFz] 342 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 343 | CursorX=1 344 | CursorY=17 345 | TopLine=1 346 | LeftCol=1 347 | Elisions= 348 | Bookmarks= 349 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 350 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 351 | c3RiZWQucGFz] 352 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 353 | CursorX=13 354 | CursorY=518 355 | TopLine=467 356 | LeftCol=1 357 | Elisions= 358 | Bookmarks= 359 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 360 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVGVz 361 | dGJlZC5kcHI=] 362 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\Testbed.dpr 363 | CursorX=33 364 | CursorY=27 365 | TopLine=1 366 | LeftCol=1 367 | Elisions= 368 | Bookmarks= 369 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\Testbed.dpr 370 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVGVz 371 | dGJlZC5kcHI=] 372 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\Testbed.dpr 373 | CursorX=33 374 | CursorY=27 375 | TopLine=1 376 | LeftCol=1 377 | Elisions= 378 | Bookmarks= 379 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\Testbed.dpr 380 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVGVz 381 | dGJlZC5kcHI=] 382 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\Testbed.dpr 383 | CursorX=1 384 | CursorY=1 385 | TopLine=1 386 | LeftCol=1 387 | Elisions= 388 | Bookmarks= 389 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\Testbed.dpr 390 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 391 | c3RiZWQucGFz] 392 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 393 | CursorX=6 394 | CursorY=501 395 | TopLine=481 396 | LeftCol=1 397 | Elisions= 398 | Bookmarks= 399 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 400 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 401 | c3RiZWQucGFz] 402 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 403 | CursorX=17 404 | CursorY=495 405 | TopLine=466 406 | LeftCol=1 407 | Elisions= 408 | Bookmarks= 409 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 410 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 411 | c3RiZWQucGFz] 412 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 413 | CursorX=5 414 | CursorY=528 415 | TopLine=454 416 | LeftCol=1 417 | Elisions= 418 | Bookmarks= 419 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 420 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 421 | c3RiZWQucGFz] 422 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 423 | CursorX=49 424 | CursorY=514 425 | TopLine=472 426 | LeftCol=1 427 | Elisions= 428 | Bookmarks= 429 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 430 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 431 | c3RiZWQucGFz] 432 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 433 | CursorX=19 434 | CursorY=517 435 | TopLine=472 436 | LeftCol=1 437 | Elisions= 438 | Bookmarks= 439 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 440 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 441 | c3RiZWQucGFz] 442 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 443 | CursorX=39 444 | CursorY=517 445 | TopLine=472 446 | LeftCol=1 447 | Elisions= 448 | Bookmarks= 449 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 450 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 451 | c3RiZWQucGFz] 452 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 453 | CursorX=21 454 | CursorY=568 455 | TopLine=505 456 | LeftCol=1 457 | Elisions= 458 | Bookmarks= 459 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 460 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 461 | c3RiZWQucGFz] 462 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 463 | CursorX=13 464 | CursorY=586 465 | TopLine=550 466 | LeftCol=1 467 | Elisions= 468 | Bookmarks= 469 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 470 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 471 | c3RiZWQucGFz] 472 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 473 | CursorX=13 474 | CursorY=672 475 | TopLine=503 476 | LeftCol=1 477 | Elisions= 478 | Bookmarks= 479 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 480 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 481 | c3RiZWQucGFz] 482 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 483 | CursorX=39 484 | CursorY=667 485 | TopLine=646 486 | LeftCol=1 487 | Elisions= 488 | Bookmarks= 489 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 490 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 491 | c3RiZWQucGFz] 492 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 493 | CursorX=13 494 | CursorY=705 495 | TopLine=667 496 | LeftCol=1 497 | Elisions= 498 | Bookmarks= 499 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 500 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 501 | c3RiZWQucGFz] 502 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 503 | CursorX=1 504 | CursorY=641 505 | TopLine=610 506 | LeftCol=1 507 | Elisions= 508 | Bookmarks= 509 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 510 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 511 | c3RiZWQucGFz] 512 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 513 | CursorX=1 514 | CursorY=659 515 | TopLine=634 516 | LeftCol=1 517 | Elisions= 518 | Bookmarks= 519 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 520 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 521 | c3RiZWQucGFz] 522 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 523 | CursorX=11 524 | CursorY=708 525 | TopLine=693 526 | LeftCol=1 527 | Elisions= 528 | Bookmarks= 529 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 530 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 531 | c3RiZWQucGFz] 532 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 533 | CursorX=11 534 | CursorY=708 535 | TopLine=693 536 | LeftCol=1 537 | Elisions= 538 | Bookmarks= 539 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 540 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 541 | c3RiZWQucGFz] 542 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 543 | CursorX=13 544 | CursorY=790 545 | TopLine=742 546 | LeftCol=1 547 | Elisions= 548 | Bookmarks= 549 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 550 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 551 | c3RiZWQucGFz] 552 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 553 | CursorX=62 554 | CursorY=722 555 | TopLine=697 556 | LeftCol=1 557 | Elisions= 558 | Bookmarks= 559 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 560 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 561 | c3RiZWQucGFz] 562 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 563 | CursorX=76 564 | CursorY=776 565 | TopLine=770 566 | LeftCol=1 567 | Elisions= 568 | Bookmarks= 569 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 570 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 571 | c3RiZWQucGFz] 572 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 573 | CursorX=39 574 | CursorY=458 575 | TopLine=449 576 | LeftCol=1 577 | Elisions= 578 | Bookmarks= 579 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 580 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 581 | c3RiZWQucGFz] 582 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 583 | CursorX=17 584 | CursorY=234 585 | TopLine=13 586 | LeftCol=1 587 | Elisions= 588 | Bookmarks= 589 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 590 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 591 | c3RiZWQucGFz] 592 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 593 | CursorX=1 594 | CursorY=896 595 | TopLine=792 596 | LeftCol=1 597 | Elisions= 598 | Bookmarks= 599 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 600 | 601 | [ClosedView_QzpcRGV2XERlbHBoaVxQcm9qZWN0c1xFYXN5SnNvblxyZXBvXGV4YW1wbGVzXHRlc3RiZWRcVVRl 602 | c3RiZWQucGFz] 603 | Module=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 604 | CursorX=53 605 | CursorY=808 606 | TopLine=852 607 | LeftCol=1 608 | Elisions= 609 | Bookmarks= 610 | EditViewName=C:\Dev\Delphi\Projects\EasyJson\repo\examples\testbed\UTestbed.pas 611 | 612 | -------------------------------------------------------------------------------- /examples/testbed/Testbed.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinyBigGAMES/EasyJson/a04c879db38ffe9fbf6e4a142be33c90c84a27b1/examples/testbed/Testbed.res -------------------------------------------------------------------------------- /examples/testbed/Testbed_Icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinyBigGAMES/EasyJson/a04c879db38ffe9fbf6e4a142be33c90c84a27b1/examples/testbed/Testbed_Icon.ico -------------------------------------------------------------------------------- /examples/testbed/UTestbed.pas: -------------------------------------------------------------------------------- 1 | {=============================================================================== 2 | ___ _ 3 | | __|__ _ ____ _ _ | |___ ___ _ _ ™ 4 | | _|/ _` (_-< || | || (_- 33 | /// Specifies whether a TEasyJson instance owns the JSON value 34 | /// it is handling or merely holds a reference to it. 35 | /// 36 | TEjValueOwnership = (ejOwned, ejReference); 37 | 38 | /// 39 | /// TEasyJson is a fluent interface class designed to simplify 40 | /// working with JSON objects and arrays in Delphi. 41 | /// 42 | /// 43 | /// This class provides an intuitive way to manipulate JSON structures, 44 | /// allowing dynamic creation, modification, and retrieval of JSON data 45 | /// using method chaining. It supports both JSON objects and arrays, 46 | /// making it easy to construct complex JSON documents with minimal code. 47 | /// 48 | /// 49 | /// Key Features: 50 | /// 51 | /// Fluent API for intuitive JSON construction. 52 | /// Supports nested objects and arrays. 53 | /// Seamless conversion of JSON values to native Delphi types. 54 | /// Formatted and compact JSON serialization. 55 | /// 56 | /// 57 | /// 58 | /// Creating a JSON object with nested properties and arrays: 59 | /// 60 | /// var EJ: TEasyJson; 61 | /// begin 62 | /// EJ := TEasyJson.Create; 63 | /// EJ.Put('name', 'Alice') 64 | /// .Put('age', 25) 65 | /// .AddArray('hobbies') 66 | /// .Put(0, 'Reading') 67 | /// .Put(1, 'Cycling') 68 | /// .AddObject('address') 69 | /// .Put('city', 'New York') 70 | /// .Put('zipcode', '10001'); 71 | /// 72 | /// ShowMessage(EJ.Format); 73 | /// end; 74 | /// 75 | /// Output: 76 | /// 77 | /// { 78 | /// "name": "Alice", 79 | /// "age": 25, 80 | /// "hobbies": [ 81 | /// "Reading", 82 | /// "Cycling" 83 | /// ], 84 | /// "address": { 85 | /// "city": "New York", 86 | /// "zipcode": "10001" 87 | /// } 88 | /// } 89 | /// 90 | /// 91 | TEasyJson = class 92 | private 93 | FJsonValue: TJSONValue; 94 | FParent: TEasyJson; 95 | FOwnership: TejValueOwnership; 96 | FChildren: TObjectList; 97 | FOriginalKey: string; 98 | FOriginalParent: TEasyJson; 99 | FIsDirectReference: Boolean; 100 | FAnchor: TEasyJson; 101 | 102 | 103 | function GetValue(const AKeyOrIndex: Variant): TEasyJson; 104 | function CreateJsonValue(const AValue: Variant): TJSONValue; 105 | procedure SafeAddPair(const AObj: TJSONObject; const AName: string; AValue: TJSONValue); 106 | function GetOrCreateArray(const AArray: TJSONArray; AIndex: Integer): TJSONArray; 107 | function AddChild(const AChild: TEasyJson): TEasyJson; 108 | function GetValueByPath(const APath: string): TEasyJson; 109 | procedure SetValueByPath(const APath: string; const AJson: TEasyJson); 110 | procedure Clean(); 111 | 112 | public 113 | /// 114 | /// Initializes a new instance of the TEasyJson class as an empty JSON object. 115 | /// 116 | /// 117 | /// - This constructor creates an empty JSON object ({}). 118 | /// - Use this when you need to build a JSON structure dynamically. 119 | /// 120 | /// 121 | /// 122 | /// var EJ: TEasyJson; 123 | /// begin 124 | /// EJ := TEasyJson.Create; 125 | /// EJ.Put('name', 'Alice').Put('age', 25); 126 | /// ShowMessage(EJ.Format); 127 | /// end; 128 | /// 129 | /// Output: 130 | /// 131 | /// { 132 | /// "name": "Alice", 133 | /// "age": 25 134 | /// } 135 | /// 136 | /// 137 | constructor Create(); overload; 138 | 139 | /// 140 | /// Initializes a new instance of the TEasyJson class from a JSON string. 141 | /// 142 | /// 143 | /// A valid JSON-formatted string used to populate this instance. 144 | /// 145 | /// 146 | /// - If the JSON string is invalid, behavior depends on error handling (it may raise an exception or initialize an empty object). 147 | /// - The instance takes ownership of the parsed JSON structure. 148 | /// 149 | /// 150 | /// 151 | /// var EJ: TEasyJson; 152 | /// begin 153 | /// EJ := TEasyJson.Create('{"name":"Alice","age":25}'); 154 | /// ShowMessage(EJ['name'].AsString); // Outputs: Alice 155 | /// end; 156 | /// 157 | /// 158 | constructor Create(const AJson: string); overload; 159 | 160 | /// 161 | /// Initializes a new instance of the TEasyJson class from an existing TJSONValue. 162 | /// 163 | /// 164 | /// The TJSONValue object that this instance will wrap. 165 | /// 166 | /// 167 | /// Defines whether TEasyJson owns the JSON value (ejOwned) or only references it (ejReference). 168 | /// Default is ejOwned. 169 | /// 170 | /// 171 | /// - If AOwnership is set to ejOwned, TEasyJson takes responsibility for freeing AJsonValue. 172 | /// - If AOwnership is set to ejReference, the caller remains responsible for managing the lifetime of AJsonValue. 173 | /// 174 | /// 175 | /// Example with ownership: 176 | /// 177 | /// var JSONValue: TJSONObject; 178 | /// EJ: TEasyJson; 179 | /// begin 180 | /// JSONValue := TJSONObject.Create; 181 | /// EJ := TEasyJson.Create(JSONValue, ejOwned); 182 | /// EJ.Put('name', 'Bob'); 183 | /// ShowMessage(EJ.Format); 184 | /// end; 185 | /// 186 | /// 187 | /// Example with reference: 188 | /// 189 | /// var JSONValue: TJSONObject; 190 | /// EJ: TEasyJson; 191 | /// begin 192 | /// JSONValue := TJSONObject.Create; 193 | /// EJ := TEasyJson.Create(JSONValue, ejReference); 194 | /// EJ.Put('name', 'Charlie'); 195 | /// ShowMessage(JSONValue.ToString); // JSONValue still exists after EJ is freed 196 | /// EJ.Free; 197 | /// JSONValue.Free; // Caller must free the referenced value 198 | /// end; 199 | /// 200 | /// 201 | constructor Create(const AJsonValue: TJSONValue; AOwnership: TejValueOwnership = ejOwned); overload; 202 | 203 | /// 204 | /// Initializes a new instance of the TEasyJson class from an existing TJSONValue, 205 | /// associating it with a parent TEasyJson instance. 206 | /// 207 | /// 208 | /// The TJSONValue object that this instance will wrap. 209 | /// 210 | /// 211 | /// The parent TEasyJson instance that owns or manages AJsonValue. 212 | /// 213 | /// 214 | /// Defines whether TEasyJson owns the JSON value (ejOwned) or only references it (ejReference). 215 | /// Default is ejReference. 216 | /// 217 | /// 218 | /// - This constructor is typically used when a child TEasyJson instance needs to be managed 219 | /// within a larger JSON structure. 220 | /// - If AOwnership is set to ejReference, AParent is responsible for managing the JSON value. 221 | /// 222 | /// 223 | /// Creating a sub-object inside a parent JSON structure: 224 | /// 225 | /// var ParentJson, SubJson: TEasyJson; 226 | /// begin 227 | /// ParentJson := TEasyJson.Create; 228 | /// SubJson := TEasyJson.Create(ParentJson.AddObject('address'), ParentJson, ejReference); 229 | /// SubJson.Put('city', 'New York').Put('zipcode', '10001'); 230 | /// ShowMessage(ParentJson.Format); 231 | /// end; 232 | /// 233 | /// Output: 234 | /// 235 | /// { 236 | /// "address": { 237 | /// "city": "New York", 238 | /// "zipcode": "10001" 239 | /// } 240 | /// } 241 | /// 242 | /// 243 | constructor Create(const AJsonValue: TJSONValue; AParent: TEasyJson; AOwnership: TejValueOwnership = ejReference); overload; 244 | 245 | /// 246 | /// Destroys the TEasyJson instance and frees allocated resources. 247 | /// 248 | /// 249 | /// - If the instance owns the JSON value (ejOwned), it will be automatically freed. 250 | /// - If the instance only references a JSON value (ejReference), the caller is responsible 251 | /// for freeing the referenced JSON object. 252 | /// - Any child objects or arrays created under this instance will also be cleaned up accordingly. 253 | /// 254 | /// 255 | /// Example of automatic cleanup with ownership: 256 | /// 257 | /// var EJ: TEasyJson; 258 | /// begin 259 | /// EJ := TEasyJson.Create; 260 | /// try 261 | /// EJ.Put('name', 'Alice'); 262 | /// ShowMessage(EJ.Format); 263 | /// finally 264 | /// EJ.Free; // Automatically frees the JSON structure 265 | /// end; 266 | /// end; 267 | /// 268 | /// 269 | destructor Destroy(); override; 270 | 271 | /// 272 | /// Clears the JSON structure, resetting it to an empty state. 273 | /// 274 | /// 275 | /// - If this instance represents a JSON object, all key-value pairs are removed. 276 | /// - If this instance represents a JSON array, all elements are removed. 277 | /// - The instance remains valid and can be reused to construct a new JSON structure. 278 | /// 279 | /// 280 | /// The following example demonstrates how Clear resets a JSON object: 281 | /// 282 | /// var EJ: TEasyJson; 283 | /// begin 284 | /// EJ := TEasyJson.Create; 285 | /// EJ.Put('name', 'Alice').Put('age', 25); 286 | /// ShowMessage(EJ.Format); // Outputs JSON with data 287 | /// 288 | /// EJ.Clear; 289 | /// ShowMessage(EJ.Format); // Outputs: {} 290 | /// end; 291 | /// 292 | /// 293 | procedure Clear(); 294 | 295 | /// 296 | /// Loads a JSON structure from a file. 297 | /// 298 | /// 299 | /// The full path to the file containing the JSON data. 300 | /// 301 | /// 302 | /// True if the JSON data was successfully loaded, False otherwise. 303 | /// 304 | /// 305 | /// - The file must contain valid JSON; otherwise, the function returns False. 306 | /// - The existing content of the TEasyJson instance will be replaced with the loaded data. 307 | /// - If the file does not exist or cannot be read, the function returns False. 308 | /// 309 | /// 310 | /// The following example loads a JSON file: 311 | /// 312 | /// var EJ: TEasyJson; 313 | /// begin 314 | /// EJ := TEasyJson.Create; 315 | /// if EJ.LoadFromFile('C:\data.json') then 316 | /// ShowMessage(EJ.Format) 317 | /// else 318 | /// ShowMessage('Failed to load JSON file'); 319 | /// end; 320 | /// 321 | /// 322 | function LoadFromFile(const AFilename: string): Boolean; 323 | 324 | /// 325 | /// Saves the JSON structure to a file. 326 | /// 327 | /// 328 | /// The full path to the file where the JSON data will be saved. 329 | /// 330 | /// 331 | /// True if the JSON data was successfully saved, False otherwise. 332 | /// 333 | /// 334 | /// - If the file already exists, it will be overwritten. 335 | /// - If the JSON structure is empty, an empty JSON object {} will be written. 336 | /// - If there are any file write errors, the function returns False. 337 | /// 338 | /// 339 | /// The following example saves a JSON object to a file: 340 | /// 341 | /// var EJ: TEasyJson; 342 | /// begin 343 | /// EJ := TEasyJson.Create; 344 | /// EJ.Put('name', 'Alice').Put('age', 25); 345 | /// if EJ.SaveToFile('C:\output.json') then 346 | /// ShowMessage('JSON saved successfully') 347 | /// else 348 | /// ShowMessage('Failed to save JSON file'); 349 | /// end; 350 | /// 351 | /// 352 | function SaveToFile(const AFilename: string): Boolean; 353 | 354 | /// 355 | /// Checks if a JSON path exists within the JSON structure. 356 | /// 357 | /// 358 | /// A dot-separated path specifying the location of the JSON element to check. 359 | /// Array indices should be enclosed in square brackets (e.g., 'candidates[0].content.newProperty'). 360 | /// 361 | /// 362 | /// True if the specified path exists in the JSON structure, otherwise False. 363 | /// 364 | /// 365 | /// - The path can traverse both JSON objects and arrays. 366 | /// - Array indices should be specified using square brackets (e.g., 'items[2].name'). 367 | /// - If any part of the path does not exist, the function returns False. 368 | /// - This method does not modify the JSON structure. 369 | /// 370 | /// 371 | /// The following example demonstrates checking for the existence of a JSON path: 372 | /// 373 | /// var EJ: TEasyJson; 374 | /// begin 375 | /// EJ := TEasyJson.Create; 376 | /// EJ.AddObject('candidates') 377 | /// .AddArray.Put(0, TEasyJson.Create.Put('content', TEasyJson.Create.Put('newProperty', 'value'))); 378 | /// 379 | /// if EJ.HasPath('candidates[0].content.newProperty') then 380 | /// ShowMessage('Property exists') 381 | /// else 382 | /// ShowMessage('Property does not exist'); 383 | /// end; 384 | /// 385 | /// Expected Output: 386 | /// 387 | /// Property exists 388 | /// 389 | /// 390 | function HasPath(const APath: string): Boolean; 391 | 392 | /// 393 | /// Sets a key-value pair in the JSON object. 394 | /// 395 | /// 396 | /// The key under which the value will be stored. 397 | /// 398 | /// 399 | /// The value assigned to the key. It can be a string, number, boolean, or null. 400 | /// 401 | /// 402 | /// The modified TEasyJson instance, allowing method chaining. 403 | /// 404 | /// 405 | /// - If the key already exists, its value is updated. 406 | /// - If the key does not exist, it is created. 407 | /// - This method provides a fluent interface for easy JSON construction. 408 | /// 409 | /// 410 | /// 411 | /// var EJ: TEasyJson; 412 | /// begin 413 | /// EJ := TEasyJson.Create; 414 | /// EJ.Put('name', 'Alice').Put('age', 25); 415 | /// ShowMessage(EJ.Format); 416 | /// end; 417 | /// 418 | /// Output: 419 | /// 420 | /// { 421 | /// "name": "Alice", 422 | /// "age": 25 423 | /// } 424 | /// 425 | /// 426 | function Put(const AKey: string; const AValue: Variant): TEasyJson; overload; 427 | 428 | /// 429 | /// Sets a key-value pair in the JSON object where the value is another TEasyJson object. 430 | /// 431 | /// 432 | /// The key under which the nested JSON object will be stored. 433 | /// 434 | /// 435 | /// The TEasyJson instance that will be inserted as the value. 436 | /// 437 | /// 438 | /// The modified TEasyJson instance, enabling fluent method chaining. 439 | /// 440 | /// 441 | /// This method allows dynamic creation of nested JSON objects. 442 | /// 443 | /// 444 | /// 445 | /// var ParentJson, ChildJson: TEasyJson; 446 | /// begin 447 | /// ParentJson := TEasyJson.Create; 448 | /// ChildJson := TEasyJson.Create; 449 | /// ChildJson.Put('city', 'New York').Put('zipcode', '10001'); 450 | /// ParentJson.Put('address', ChildJson); 451 | /// ShowMessage(ParentJson.Format); 452 | /// end; 453 | /// 454 | /// Output: 455 | /// 456 | /// { 457 | /// "address": { 458 | /// "city": "New York", 459 | /// "zipcode": "10001" 460 | /// } 461 | /// } 462 | /// 463 | /// 464 | function Put(const AKey: string; const AJson: TEasyJson): TEasyJson; overload; 465 | 466 | /// 467 | /// Sets a key-value pair in the JSON object where the value is a TJSONValue. 468 | /// 469 | /// 470 | /// The key under which the JSON value will be stored. 471 | /// 472 | /// 473 | /// A TJSONValue that represents a JSON-compatible structure. 474 | /// 475 | /// 476 | /// The modified TEasyJson instance. 477 | /// 478 | function Put(const AKey: string; const AJSONValue: TJSONValue): TEasyJson; overload; 479 | 480 | /// 481 | /// Sets a value at a specific index in a JSON array. 482 | /// 483 | /// 484 | /// The zero-based index where the value will be placed. 485 | /// 486 | /// 487 | /// The value to assign at the specified index. 488 | /// 489 | /// 490 | /// The modified TEasyJson instance. 491 | /// 492 | /// 493 | /// - If the index is out of bounds, behavior depends on internal error handling. 494 | /// - This method is useful for modifying an existing JSON array. 495 | /// 496 | /// 497 | /// 498 | /// var EJ: TEasyJson; 499 | /// begin 500 | /// EJ := TEasyJson.Create; 501 | /// EJ.AddArray('numbers').Put(0, 10).Put(1, 20); 502 | /// ShowMessage(EJ.Format); 503 | /// end; 504 | /// 505 | /// Output: 506 | /// 507 | /// { 508 | /// "numbers": [10, 20] 509 | /// } 510 | /// 511 | /// 512 | function Put(const AIndex: Integer; const AValue: Variant): TEasyJson; overload; 513 | 514 | /// 515 | /// Sets a JSON array element at a specific index with another TEasyJson object. 516 | /// 517 | /// 518 | /// The zero-based index where the TEasyJson object will be stored. 519 | /// 520 | /// 521 | /// The TEasyJson instance to store at the specified index. 522 | /// 523 | /// 524 | /// The modified TEasyJson instance. 525 | /// 526 | function Put(const AIndex: Integer; const AJson: TEasyJson): TEasyJson; overload; 527 | 528 | /// 529 | /// Sets a JSON array element at a specific index with a TJSONValue. 530 | /// 531 | /// 532 | /// The zero-based index where the TJSONValue will be placed. 533 | /// 534 | /// 535 | /// The TJSONValue to store at the specified index. 536 | /// 537 | /// 538 | /// The modified TEasyJson instance. 539 | /// 540 | function Put(const AIndex: Integer; const AJSONValue: TJSONValue): TEasyJson; overload; 541 | 542 | /// 543 | /// Adds a new key-value pair to the JSON object. 544 | /// 545 | /// 546 | /// The key under which the value will be stored. 547 | /// 548 | /// 549 | /// The value assigned to the key. It can be a string, number, boolean, or null. 550 | /// 551 | /// 552 | /// The modified TEasyJson instance, allowing method chaining. 553 | /// 554 | /// 555 | /// - If the key already exists, this method does not replace the existing value. 556 | /// - If you need to update an existing key, use the Set method instead. 557 | /// - This method is useful for building JSON objects dynamically where keys are unique. 558 | /// 559 | /// 560 | /// 561 | /// var EJ: TEasyJson; 562 | /// begin 563 | /// EJ := TEasyJson.Create; 564 | /// EJ.Add('name', 'Alice').Add('age', 25); 565 | /// ShowMessage(EJ.Format); 566 | /// end; 567 | /// 568 | /// Output: 569 | /// 570 | /// { 571 | /// "name": "Alice", 572 | /// "age": 25 573 | /// } 574 | /// 575 | /// 576 | function Add(const AKey: string; const AValue: Variant): TEasyJson; overload; 577 | 578 | /// 579 | /// Adds a new key with a TEasyJson object as its value. 580 | /// 581 | /// 582 | /// The key under which the nested JSON object will be stored. 583 | /// 584 | /// 585 | /// The TEasyJson instance that will be inserted as a value. 586 | /// 587 | /// 588 | /// The modified TEasyJson instance. 589 | /// 590 | /// 591 | /// - The provided AJson instance is inserted as a sub-object. 592 | /// - This method does not copy the instance; it references the passed AJson object. 593 | /// 594 | /// 595 | /// 596 | /// var ParentJson, ChildJson: TEasyJson; 597 | /// begin 598 | /// ParentJson := TEasyJson.Create; 599 | /// ChildJson := TEasyJson.Create; 600 | /// ChildJson.Put('city', 'New York').Put('zipcode', '10001'); 601 | /// ParentJson.Add('address', ChildJson); 602 | /// ShowMessage(ParentJson.Format); 603 | /// end; 604 | /// 605 | /// Output: 606 | /// 607 | /// { 608 | /// "address": { 609 | /// "city": "New York", 610 | /// "zipcode": "10001" 611 | /// } 612 | /// } 613 | /// 614 | /// 615 | function Add(const AKey: string; const AJson: TEasyJson): TEasyJson; overload; 616 | 617 | /// 618 | /// Adds a new key with a TJSONValue as its value. 619 | /// 620 | /// 621 | /// The key under which the JSON value will be stored. 622 | /// 623 | /// 624 | /// The TJSONValue that will be stored as the value. 625 | /// 626 | /// 627 | /// The modified TEasyJson instance. 628 | /// 629 | /// 630 | /// - This method is useful for working with raw TJSONValue objects. 631 | /// - Ownership of the provided AJSONValue remains with the caller. 632 | /// 633 | function Add(const AKey: string; const AJSONValue: TJSONValue): TEasyJson; overload; 634 | 635 | /// 636 | /// Adds a new key with a TJSONObject as its value. 637 | /// 638 | /// 639 | /// The key under which the JSON object will be stored. 640 | /// 641 | /// 642 | /// The TJSONObject instance that will be inserted as the value. 643 | /// 644 | /// 645 | /// The modified TEasyJson instance. 646 | /// 647 | /// 648 | /// - This method allows direct insertion of a TJSONObject. 649 | /// - Unlike TEasyJson, TJSONObject does not support fluent chaining. 650 | /// 651 | function Add(const AKey: string; const AObject: TJSONObject): TEasyJson; overload; 652 | 653 | /// 654 | /// Adds a new key with a TJSONArray as its value. 655 | /// 656 | /// 657 | /// The key under which the JSON array will be stored. 658 | /// 659 | /// 660 | /// The TJSONArray instance to be inserted as a value. 661 | /// 662 | /// 663 | /// The modified TEasyJson instance. 664 | /// 665 | /// 666 | /// - This method is useful when adding pre-constructed JSON arrays into an object. 667 | /// - Ownership of the provided AnArray remains with the caller. 668 | /// 669 | /// 670 | /// 671 | /// var EJ: TEasyJson; 672 | /// Arr: TJSONArray; 673 | /// begin 674 | /// EJ := TEasyJson.Create; 675 | /// Arr := TJSONArray.Create; 676 | /// Arr.Add(10); 677 | /// Arr.Add(20); 678 | /// EJ.Add('numbers', Arr); 679 | /// ShowMessage(EJ.Format); 680 | /// end; 681 | /// 682 | /// Output: 683 | /// 684 | /// { 685 | /// "numbers": [10, 20] 686 | /// } 687 | /// 688 | /// 689 | function Add(const AKey: string; const AnArray: TJSONArray): TEasyJson; overload; 690 | 691 | /// 692 | /// Adds an unnamed empty object to the JSON structure. 693 | /// 694 | /// 695 | /// A new TEasyJson instance representing the added object. 696 | /// 697 | /// 698 | /// - This method appends an empty object ({}) to the JSON structure. 699 | /// - It is primarily used when adding objects inside an array. 700 | /// 701 | /// 702 | /// The following example adds an empty object inside an array: 703 | /// 704 | /// var EJ: TEasyJson; 705 | /// begin 706 | /// EJ := TEasyJson.Create; 707 | /// EJ.AddArray('people') 708 | /// .AddObject 709 | /// .Put('name', 'Alice') 710 | /// .Put('age', 25); 711 | /// ShowMessage(EJ.Format); 712 | /// end; 713 | /// 714 | /// Output: 715 | /// 716 | /// { 717 | /// "people": [ 718 | /// { 719 | /// "name": "Alice", 720 | /// "age": 25 721 | /// } 722 | /// ] 723 | /// } 724 | /// 725 | /// 726 | function AddObject(): TEasyJson; overload; 727 | 728 | /// 729 | /// Adds a named empty object to the JSON structure. 730 | /// 731 | /// 732 | /// The key under which the new object will be stored. 733 | /// 734 | /// 735 | /// A new TEasyJson instance representing the added object. 736 | /// 737 | /// 738 | /// - This method is useful when inserting an empty object into a JSON dictionary, 739 | /// where additional properties will be added later. 740 | /// 741 | /// 742 | /// The following example adds an empty object with a key: 743 | /// 744 | /// var EJ: TEasyJson; 745 | /// begin 746 | /// EJ := TEasyJson.Create; 747 | /// EJ.AddObject('address').Put('city', 'New York').Put('zipcode', '10001'); 748 | /// ShowMessage(EJ.Format); 749 | /// end; 750 | /// 751 | /// Output: 752 | /// 753 | /// { 754 | /// "address": { 755 | /// "city": "New York", 756 | /// "zipcode": "10001" 757 | /// } 758 | /// } 759 | /// 760 | /// 761 | function AddObject(const AKey: string): TEasyJson; overload; 762 | 763 | /// 764 | /// Adds a named object to the JSON structure using a callback function 765 | /// for inline object creation. 766 | /// 767 | /// 768 | /// The key under which the new object will be stored. 769 | /// 770 | /// 771 | /// A callback function that receives a TEasyJson instance 772 | /// and allows inline object construction. 773 | /// 774 | /// 775 | /// The modified TEasyJson instance. 776 | /// 777 | /// 778 | /// The following example adds a nested object using a callback function: 779 | /// 780 | /// var EJ: TEasyJson; 781 | /// begin 782 | /// EJ := TEasyJson.Create; 783 | /// EJ.AddObject('person', 784 | /// function(EJ: TEasyJson): TEasyJson 785 | /// begin 786 | /// Result := EJ 787 | /// .Put('name', 'John') 788 | /// .Put('age', 30); 789 | /// end); 790 | /// ShowMessage(EJ.Format); 791 | /// end; 792 | /// 793 | /// Output: 794 | /// 795 | /// { 796 | /// "person": { 797 | /// "name": "John", 798 | /// "age": 30 799 | /// } 800 | /// } 801 | /// 802 | /// 803 | function AddObject(const AKey: string; const AFunc: TFunc): TEasyJson; overload; 804 | 805 | /// 806 | /// Adds an anonymous object to the JSON structure using a callback function. 807 | /// 808 | /// 809 | /// A callback function that receives a TEasyJson instance 810 | /// and allows inline object construction. 811 | /// 812 | /// 813 | /// The modified TEasyJson instance. 814 | /// 815 | /// 816 | /// The following example adds an object dynamically inside an array: 817 | /// 818 | /// var EJ: TEasyJson; 819 | /// begin 820 | /// EJ := TEasyJson.Create; 821 | /// EJ.AddArray('people') 822 | /// .AddObject( 823 | /// function(EJ: TEasyJson): TEasyJson 824 | /// begin 825 | /// Result := EJ 826 | /// .Put('name', 'Alice') 827 | /// .Put('age', 25); 828 | /// end); 829 | /// ShowMessage(EJ.Format); 830 | /// end; 831 | /// 832 | /// Output: 833 | /// 834 | /// { 835 | /// "people": [ 836 | /// { 837 | /// "name": "Alice", 838 | /// "age": 25 839 | /// } 840 | /// ] 841 | /// } 842 | /// 843 | /// 844 | function AddObject(const AFunc: TFunc): TEasyJson; overload; 845 | 846 | /// 847 | /// Adds an unnamed empty array to the JSON structure. 848 | /// 849 | /// 850 | /// A new TEasyJson instance representing the added array. 851 | /// 852 | /// 853 | /// - This method appends an empty array ([]) to the JSON structure. 854 | /// - It is primarily used when adding arrays inside an existing JSON structure. 855 | /// 856 | /// 857 | /// The following example adds an empty array inside an object: 858 | /// 859 | /// var EJ: TEasyJson; 860 | /// begin 861 | /// EJ := TEasyJson.Create; 862 | /// EJ.AddObject('data').AddArray; 863 | /// ShowMessage(EJ.Format); 864 | /// end; 865 | /// 866 | /// Output: 867 | /// 868 | /// { 869 | /// "data": [] 870 | /// } 871 | /// 872 | /// 873 | function AddArray(): TEasyJson; overload; 874 | 875 | /// 876 | /// Adds a named empty array to the JSON structure. 877 | /// 878 | /// 879 | /// The key under which the new array will be stored. 880 | /// 881 | /// 882 | /// A new TEasyJson instance representing the added array. 883 | /// 884 | /// 885 | /// - This method is useful when inserting an empty array into a JSON object 886 | /// where elements will be added later. 887 | /// 888 | /// 889 | /// The following example adds an empty array with a key: 890 | /// 891 | /// var EJ: TEasyJson; 892 | /// begin 893 | /// EJ := TEasyJson.Create; 894 | /// EJ.AddArray('numbers'); 895 | /// ShowMessage(EJ.Format); 896 | /// end; 897 | /// 898 | /// Output: 899 | /// 900 | /// { 901 | /// "numbers": [] 902 | /// } 903 | /// 904 | /// 905 | function AddArray(const AKey: string): TEasyJson; overload; 906 | 907 | /// 908 | /// Navigates back to the parent TEasyJson instance. 909 | /// 910 | /// 911 | /// The parent TEasyJson instance, allowing fluent navigation. 912 | /// 913 | /// 914 | /// - This method is useful when working with nested JSON structures. 915 | /// - If called on the root instance, it may return itself or nil, 916 | /// depending on the implementation. 917 | /// - Designed to facilitate working within deeply nested JSON objects 918 | /// while maintaining a fluent API. 919 | /// 920 | /// 921 | /// The following example demonstrates how Back can be used to 922 | /// navigate back from a nested JSON object: 923 | /// 924 | /// var EJ: TEasyJson; 925 | /// begin 926 | /// EJ := TEasyJson.Create; 927 | /// EJ.AddObject('person') 928 | /// .Put('name', 'Alice') 929 | /// .Put('age', 25) 930 | /// .Back() // Navigates back to the root 931 | /// .Put('status', 'active'); 932 | /// 933 | /// ShowMessage(EJ.Format); 934 | /// end; 935 | /// 936 | /// Output: 937 | /// 938 | /// { 939 | /// "person": { 940 | /// "name": "Alice", 941 | /// "age": 25 942 | /// }, 943 | /// "status": "active" 944 | /// } 945 | /// 946 | /// 947 | function Back(): TEasyJson; 948 | 949 | /// 950 | /// Navigates to the root TEasyJson instance. 951 | /// 952 | /// 953 | /// The root TEasyJson instance. 954 | /// 955 | /// 956 | /// - This method allows easy access back to the root JSON object from 957 | /// any nested level. 958 | /// - If called on the root instance, it returns itself. 959 | /// 960 | /// 961 | /// The following example demonstrates how Root can be used 962 | /// to return to the top-level JSON object: 963 | /// 964 | /// var EJ: TEasyJson; 965 | /// begin 966 | /// EJ := TEasyJson.Create; 967 | /// EJ.AddObject('company') 968 | /// .AddObject('address') 969 | /// .Put('city', 'New York') 970 | /// .Put('zipcode', '10001') 971 | /// .Root() // Navigates back to the root 972 | /// .Put('name', 'TechCorp'); 973 | /// 974 | /// ShowMessage(EJ.Format); 975 | /// end; 976 | /// 977 | /// Output: 978 | /// 979 | /// { 980 | /// "company": { 981 | /// "address": { 982 | /// "city": "New York", 983 | /// "zipcode": "10001" 984 | /// } 985 | /// }, 986 | /// "name": "TechCorp" 987 | /// } 988 | /// 989 | /// 990 | function Root(): TEasyJson; 991 | 992 | /// 993 | /// Returns the number of elements in the JSON object or array. 994 | /// 995 | /// 996 | /// An integer representing the number of key-value pairs in a JSON object 997 | /// or the number of elements in a JSON array. 998 | /// 999 | /// 1000 | /// - If this instance represents a JSON object, Count returns the number of keys. 1001 | /// - If this instance represents a JSON array, Count returns the number of elements. 1002 | /// - If this instance is empty, Count returns 0. 1003 | /// 1004 | /// 1005 | /// The following example demonstrates how Count behaves: 1006 | /// 1007 | /// var EJ: TEasyJson; 1008 | /// begin 1009 | /// EJ := TEasyJson.Create; 1010 | /// EJ.Put('name', 'Alice').Put('age', 25); 1011 | /// ShowMessage(IntToStr(EJ.Count)); // Outputs: 2 1012 | /// end; 1013 | /// 1014 | /// 1015 | function Count(): Integer; 1016 | 1017 | /// 1018 | /// Serializes the JSON object into a compact string representation. 1019 | /// 1020 | /// 1021 | /// A string containing the JSON data in a single-line format. 1022 | /// 1023 | /// 1024 | /// - The returned JSON string does not include line breaks or indentation. 1025 | /// - Use Format instead if you need human-readable formatting. 1026 | /// 1027 | /// 1028 | /// The following example converts a JSON object to a string: 1029 | /// 1030 | /// var EJ: TEasyJson; 1031 | /// begin 1032 | /// EJ := TEasyJson.Create; 1033 | /// EJ.Put('name', 'Alice').Put('age', 25); 1034 | /// ShowMessage(EJ.ToString); 1035 | /// // Outputs: {"name":"Alice","age":25} 1036 | /// end; 1037 | /// 1038 | /// 1039 | function ToString(): string; override; 1040 | 1041 | /// 1042 | /// Returns a formatted JSON string with indentation for readability. 1043 | /// 1044 | /// 1045 | /// The number of spaces used for indentation. Default is 4. 1046 | /// 1047 | /// 1048 | /// A string containing a human-readable, pretty-printed JSON structure. 1049 | /// 1050 | /// 1051 | /// - This method ensures that the JSON output is properly formatted with 1052 | /// line breaks and indentation. 1053 | /// - Useful for debugging and displaying JSON data in a readable format. 1054 | /// 1055 | /// 1056 | /// The following example generates a formatted JSON output: 1057 | /// 1058 | /// var EJ: TEasyJson; 1059 | /// begin 1060 | /// EJ := TEasyJson.Create; 1061 | /// EJ.Put('name', 'Alice').Put('age', 25); 1062 | /// ShowMessage(EJ.Format); 1063 | /// end; 1064 | /// 1065 | /// Output: 1066 | /// 1067 | /// { 1068 | /// "name": "Alice", 1069 | /// "age": 25 1070 | /// } 1071 | /// 1072 | /// 1073 | function Format(const AIndentation: Integer = 4): string; 1074 | 1075 | /// 1076 | /// Retrieves the JSON value as a string. 1077 | /// 1078 | /// 1079 | /// A string representation of the JSON value. 1080 | /// 1081 | /// 1082 | /// - If the JSON value is a string, it is returned as is. 1083 | /// - If the JSON value is a number, it is converted to a string. 1084 | /// - If the JSON value is a boolean, it is returned as 'true' or 'false'. 1085 | /// - If the JSON value is an object or array, behavior depends on implementation; 1086 | /// it may return an empty string or raise an exception. 1087 | /// 1088 | function AsString(): string; 1089 | 1090 | /// 1091 | /// Retrieves the JSON value as an Int32. 1092 | /// 1093 | /// 1094 | /// An Integer representation of the JSON value. 1095 | /// 1096 | /// 1097 | /// - If the JSON value is an integer, it is returned directly. 1098 | /// - If the JSON value is a floating-point number, it is truncated to an integer. 1099 | /// - If the JSON value is a string containing a valid number, it is converted. 1100 | /// - If the JSON value is a boolean, true is converted to 1, and false to 0. 1101 | /// - If the JSON value cannot be converted, an exception may be raised. 1102 | /// 1103 | function AsInt32(): Int32; 1104 | 1105 | /// 1106 | /// Retrieves the JSON value as an UInt32. 1107 | /// 1108 | /// 1109 | /// An Integer representation of the JSON value. 1110 | /// 1111 | /// 1112 | /// - If the JSON value is an integer, it is returned directly. 1113 | /// - If the JSON value is a floating-point number, it is truncated to an integer. 1114 | /// - If the JSON value is a string containing a valid number, it is converted. 1115 | /// - If the JSON value is a boolean, true is converted to 1, and false to 0. 1116 | /// - If the JSON value cannot be converted, an exception may be raised. 1117 | /// 1118 | function AsUInt32(): UInt32; 1119 | 1120 | /// 1121 | /// Retrieves the JSON value as a signed 64-bit integer (Int64). 1122 | /// 1123 | /// 1124 | /// The JSON value converted to an Int64. 1125 | /// 1126 | /// 1127 | /// - If the JSON value is already an integer within the 64-bit signed range, it is returned directly. 1128 | /// - If the JSON value is a floating-point number, it is truncated to an Int64. 1129 | /// - If the JSON value is a string containing a valid number, it is parsed and converted. 1130 | /// - If the JSON value is a boolean, true is converted to 1, and false to 0. 1131 | /// - If the value cannot be converted to a 64-bit signed integer, an exception may be raised. 1132 | /// 1133 | /// 1134 | /// 1135 | /// var EJ: TEasyJson; 1136 | /// begin 1137 | /// EJ := TEasyJson.Create; 1138 | /// EJ.Put('bigValue', 9223372036854775807); 1139 | /// ShowMessage(IntToStr(EJ['bigValue'].AsInt64)); // Outputs: 9223372036854775807 1140 | /// end; 1141 | /// 1142 | /// 1143 | function AsInt64(): Int64; 1144 | 1145 | /// 1146 | /// Retrieves the JSON value as an unsigned 64-bit integer (UInt64). 1147 | /// 1148 | /// 1149 | /// The JSON value converted to a UInt64. 1150 | /// 1151 | /// 1152 | /// - If the JSON value is a non-negative integer within the UInt64 range, it is returned directly. 1153 | /// - If the JSON value is a floating-point number, it is truncated. 1154 | /// - If the value is a numeric string, it is parsed and converted. 1155 | /// - If the value is a boolean, true is converted to 1, and false to 0. 1156 | /// - If the value is negative or cannot be converted to UInt64, an exception may be raised. 1157 | /// 1158 | /// 1159 | /// 1160 | /// var EJ: TEasyJson; 1161 | /// begin 1162 | /// EJ := TEasyJson.Create; 1163 | /// EJ.Put('unsignedValue', '18446744073709551615'); 1164 | /// ShowMessage(UIntToStr(EJ['unsignedValue'].AsUInt64)); // Outputs: 18446744073709551615 1165 | /// end; 1166 | /// 1167 | /// 1168 | function AsUInt64(): UInt64; 1169 | 1170 | /// 1171 | /// Retrieves the JSON value as a floating-point number. 1172 | /// 1173 | /// 1174 | /// A Double representation of the JSON value. 1175 | /// 1176 | /// 1177 | /// - If the JSON value is a floating-point number, it is returned as is. 1178 | /// - If the JSON value is an integer, it is converted to a floating-point number. 1179 | /// - If the JSON value is a string containing a valid number, it is parsed as a floating-point value. 1180 | /// - If the JSON value is a boolean, true is converted to 1.0, and false to 0.0. 1181 | /// - If the JSON value cannot be converted, an exception may be raised. 1182 | /// 1183 | function AsFloat(): Double; 1184 | 1185 | /// 1186 | /// Retrieves the JSON value as a boolean. 1187 | /// 1188 | /// 1189 | /// A Boolean representation of the JSON value. 1190 | /// 1191 | /// 1192 | /// - If the JSON value is a boolean, it is returned as is. 1193 | /// - If the JSON value is a string, it is interpreted as follows: 1194 | /// - 'true' (case insensitive) returns True. 1195 | /// - 'false' (case insensitive) returns False. 1196 | /// - If the JSON value is a number: 1197 | /// - 0 is treated as False. 1198 | /// - Any nonzero value is treated as True. 1199 | /// - If the JSON value is an object or array, an exception may be raised. 1200 | /// 1201 | function AsBoolean(): Boolean; 1202 | 1203 | /// 1204 | /// Retrieves the internal JSON structure as a TJSONObject. 1205 | /// 1206 | /// 1207 | /// The internal JSON object as a TJSONObject instance. 1208 | /// 1209 | /// 1210 | /// - This method returns the underlying JSON object if the current value is a TJSONObject. 1211 | /// - If the value is not an object (e.g., it's an array or a primitive), the method may return nil or raise an exception depending on implementation. 1212 | /// - This is useful for interoperability with Delphi's built-in JSON processing routines. 1213 | /// 1214 | /// 1215 | /// 1216 | /// var EJ: TEasyJson; 1217 | /// Obj: TJSONObject; 1218 | /// begin 1219 | /// EJ := TEasyJson.Create('{"name":"Alice","age":30}'); 1220 | /// Obj := EJ.AsObject; 1221 | /// ShowMessage(Obj.GetValue('name').Value); // Outputs: Alice 1222 | /// end; 1223 | /// 1224 | /// 1225 | function AsObject(): TJSONObject; 1226 | 1227 | /// 1228 | /// Retrieves the internal JSON structure as a TJSONArray. 1229 | /// 1230 | /// 1231 | /// The internal JSON array as a TJSONArray instance. 1232 | /// 1233 | /// 1234 | /// - This method returns the underlying JSON array if the current value is a TJSONArray. 1235 | /// - If the value is not an array (e.g., it's an object or primitive), the method may return nil or raise an exception depending on implementation. 1236 | /// - This is useful when you need to pass the array to a routine that expects a native TJSONArray. 1237 | /// 1238 | /// 1239 | /// 1240 | /// var EJ: TEasyJson; 1241 | /// Arr: TJSONArray; 1242 | /// begin 1243 | /// EJ := TEasyJson.Create; 1244 | /// EJ.AddArray('values').Put(0, 10).Put(1, 20); 1245 | /// Arr := EJ['values'].AsArray; 1246 | /// ShowMessage(IntToStr(Arr.Items[1].AsType)); // Outputs: 20 1247 | /// end; 1248 | /// 1249 | /// 1250 | function AsArray(): TJSONArray; 1251 | 1252 | /// 1253 | /// Retrieves the underlying TJSONValue instance associated with this TEasyJson. 1254 | /// 1255 | /// 1256 | /// The internal TJSONValue being wrapped by this TEasyJson instance. 1257 | /// 1258 | /// 1259 | /// - This is a low-level accessor for when you need direct access to the raw JSON value. 1260 | /// - The returned value may be a TJSONObject, TJSONArray, or a primitive JSON value. 1261 | /// - Use this when integrating with other Delphi components or libraries that operate directly on TJSONValue. 1262 | /// 1263 | /// 1264 | /// 1265 | /// var EJ: TEasyJson; 1266 | /// JVal: TJSONValue; 1267 | /// begin 1268 | /// EJ := TEasyJson.Create; 1269 | /// EJ.Put('active', True); 1270 | /// JVal := EJ['active'].AsJSONValue; 1271 | /// ShowMessage(JVal.ToString); // Outputs: true 1272 | /// end; 1273 | /// 1274 | /// 1275 | function AsJSONValue(): TJSONValue; 1276 | 1277 | /// 1278 | /// Retrieves the version of the TEasyJson library in 1279 | /// Semantic Versioning (SemVer) format. 1280 | /// 1281 | /// 1282 | /// A string representing the version number in the format 1283 | /// major.minor.patch (e.g., 1.2.3). 1284 | /// 1285 | /// 1286 | /// - The version follows the Semantic Versioning (SemVer) standard: 1287 | /// 1288 | /// Major - Increases when incompatible API changes are made. 1289 | /// Minor - Increases when functionality is added in a backward-compatible manner. 1290 | /// Patch - Increases when backward-compatible bug fixes are made. 1291 | /// 1292 | /// - This method allows developers to check which version of TEasyJson is being used 1293 | /// in their project for debugging or compatibility checks. 1294 | /// 1295 | /// 1296 | /// The following example retrieves and displays the current version: 1297 | /// 1298 | /// var Version: string; 1299 | /// begin 1300 | /// Version := TEasyJson.GetVersion; 1301 | /// ShowMessage('TEasyJson Version: ' + Version); 1302 | /// end; 1303 | /// 1304 | /// Example output: 1305 | /// 1306 | /// TEasyJson Version: 1.0.0 1307 | /// 1308 | /// 1309 | class function GetVersion(): string; 1310 | 1311 | /// 1312 | /// Provides indexed access to JSON elements by key (for objects) or index (for arrays). 1313 | /// 1314 | /// 1315 | /// The key (if accessing a JSON object) or index (if accessing a JSON array) of the element. 1316 | /// 1317 | /// 1318 | /// A TEasyJson instance representing the requested JSON element. 1319 | /// 1320 | /// 1321 | /// - If this instance represents a JSON object, AKeyOrIndex must be a string corresponding 1322 | /// to a valid key in the object. 1323 | /// - If this instance represents a JSON array, AKeyOrIndex must be an integer specifying 1324 | /// the zero-based index of an element in the array. 1325 | /// - If the key does not exist in the object, behavior depends on implementation (it may return 1326 | /// nil or an empty TEasyJson instance). 1327 | /// - If the index is out of bounds, behavior depends on error handling (it may return nil or 1328 | /// raise an exception). 1329 | /// - This property supports Delphi's default property mechanism, allowing direct access via 1330 | /// EasyJson['key'] or EasyJson[0] syntax. 1331 | /// 1332 | /// 1333 | /// The following example demonstrates accessing JSON object properties: 1334 | /// 1335 | /// var EJ: TEasyJson; 1336 | /// begin 1337 | /// EJ := TEasyJson.Create; 1338 | /// EJ.Put('name', 'John').Put('age', 30); 1339 | /// ShowMessage(EJ['name'].AsString); // Outputs: John 1340 | /// end; 1341 | /// 1342 | /// 1343 | /// The following example demonstrates accessing JSON array elements: 1344 | /// 1345 | /// var EJ: TEasyJson; 1346 | /// begin 1347 | /// EJ := TEasyJson.Create; 1348 | /// EJ.AddArray('numbers').Put(0, 10).Put(1, 20); 1349 | /// ShowMessage(IntToStr(EJ['numbers'][1].AsInteger)); // Outputs: 20 1350 | /// end; 1351 | /// 1352 | /// 1353 | property Items[const AKeyOrIndex: Variant]: TEasyJson read GetValue; default; 1354 | 1355 | /// 1356 | /// Provides direct access to JSON elements using a dot-separated path. 1357 | /// 1358 | /// 1359 | /// A dot-separated string specifying the location of the JSON element. 1360 | /// Array indices should be enclosed in square brackets (e.g., 'candidates[0].content.newProperty'). 1361 | /// 1362 | /// 1363 | /// A TEasyJson instance representing the specified JSON element. 1364 | /// 1365 | /// 1366 | /// - The path can traverse both JSON objects and arrays. 1367 | /// - Array indices should be specified using square brackets (e.g., 'items[2].name'). 1368 | /// - If any part of the path does not exist, behavior depends on implementation 1369 | /// (it may return an empty instance or create missing objects dynamically). 1370 | /// - This property allows both reading and writing JSON elements dynamically. 1371 | /// 1372 | /// 1373 | /// The following example demonstrates how to access and modify JSON values using the Path property: 1374 | /// 1375 | /// var EJ: TEasyJson; 1376 | /// begin 1377 | /// EJ := TEasyJson.Create; 1378 | /// EJ.Path['candidates[0].content.newProperty'] := TEasyJson.Create.Put('value', 123); 1379 | /// 1380 | /// if EJ.HasPath('candidates[0].content.newProperty') then 1381 | /// ShowMessage(EJ.Path['candidates[0].content.newProperty']['value'].AsString); 1382 | /// end; 1383 | /// 1384 | /// Expected Output: 1385 | /// 1386 | /// 123 1387 | /// 1388 | /// 1389 | property Path[const APath: string]: TEasyJson read GetValueByPath write SetValueByPath; 1390 | 1391 | /// 1392 | /// Provides a reusable reference point within the JSON structure to allow 1393 | /// continued fluent method chaining after breaking out of a chain. 1394 | /// 1395 | /// 1396 | /// A TEasyJson instance representing the anchored point in the JSON structure. 1397 | /// 1398 | /// 1399 | /// - Use Anchor to avoid creating a separate temporary variable when you need to 1400 | /// break the fluent chain (e.g., to enter a loop or external method). 1401 | /// - Assign Anchor to the current point in the chain where you intend to return. 1402 | /// - This is especially useful when inserting elements into an array or building 1403 | /// nested structures in multiple steps. 1404 | /// - Anchor does not affect the JSON output; it is purely for developer convenience. 1405 | /// 1406 | /// 1407 | /// The following example demonstrates using Anchor to build an array inside a loop 1408 | /// without the need for a temporary variable: 1409 | /// 1410 | /// var EJ: TEasyJson; 1411 | /// I: Integer; 1412 | /// begin 1413 | /// EJ := TEasyJson.Create; 1414 | /// 1415 | /// // Create the array and anchor it for later use 1416 | /// EJ.Anchor := EJ.AddArray('items'); 1417 | /// 1418 | /// for I := 1 to 3 do 1419 | /// begin 1420 | /// EJ.Anchor.AddObject 1421 | /// .Put('id', I) 1422 | /// .Put('label', 'Item ' + IntToStr(I)); 1423 | /// end; 1424 | /// 1425 | /// ShowMessage(EJ.Format); 1426 | /// end; 1427 | /// 1428 | /// Output: 1429 | /// 1430 | /// { 1431 | /// "items": [ 1432 | /// { "id": 1, "label": "Item 1" }, 1433 | /// { "id": 2, "label": "Item 2" }, 1434 | /// { "id": 3, "label": "Item 3" } 1435 | /// ] 1436 | /// } 1437 | /// 1438 | /// 1439 | property Anchor: TEasyJson read FAnchor write FAnchor; 1440 | 1441 | end; 1442 | 1443 | implementation 1444 | 1445 | { TEasyJson } 1446 | procedure TEasyJson.Clean(); 1447 | begin 1448 | // Free all child objects 1449 | if FChildren <> nil then 1450 | begin 1451 | FChildren.Free(); 1452 | FChildren := nil; 1453 | end; 1454 | 1455 | // Free the JSON value if we own it 1456 | if (FOwnership = ejOwned) and (FJsonValue <> nil) then 1457 | begin 1458 | FJsonValue.Free(); 1459 | FJsonValue := nil; 1460 | end; 1461 | 1462 | FParent := nil; 1463 | FOwnership := ejOwned; 1464 | end; 1465 | 1466 | function TEasyJson.GetValueByPath(const APath: string): TEasyJson; 1467 | var 1468 | LPathParts: TArray; 1469 | LCurrent: TEasyJson; 1470 | LPart: string; 1471 | LArrayIndex: Integer; 1472 | LArrayPart: string; 1473 | LOpenBracket, LCloseBracket: Integer; 1474 | LIsArrayAccess: Boolean; 1475 | LChild: TEasyJson; 1476 | begin 1477 | if Trim(APath) = '' then 1478 | Exit(Self); 1479 | 1480 | LPathParts := APath.Split(['.']); 1481 | LCurrent := Self; 1482 | 1483 | for LPart in LPathParts do 1484 | begin 1485 | if LPart = '' then 1486 | Continue; 1487 | 1488 | // Check if this part contains array access [n] 1489 | LOpenBracket := Pos('[', LPart); 1490 | LCloseBracket := Pos(']', LPart); 1491 | LIsArrayAccess := (LOpenBracket > 0) and (LCloseBracket > LOpenBracket); 1492 | 1493 | if LIsArrayAccess then 1494 | begin 1495 | // Extract the object part and array index 1496 | LArrayPart := Copy(LPart, 1, LOpenBracket - 1); 1497 | if not TryStrToInt(Copy(LPart, LOpenBracket + 1, LCloseBracket - LOpenBracket - 1), LArrayIndex) then 1498 | begin 1499 | // Invalid array index, return null 1500 | Result := TEasyJson.Create(TJSONNull.Create, LCurrent, ejOwned); 1501 | Result.FOriginalParent := Self; 1502 | Result.FOriginalKey := APath; 1503 | Exit(AddChild(Result)); 1504 | end; 1505 | 1506 | // If we have an object part, navigate to it first 1507 | if LArrayPart <> '' then 1508 | begin 1509 | if (LCurrent.FJsonValue is TJSONObject) and 1510 | (TJSONObject(LCurrent.FJsonValue).GetValue(LArrayPart) <> nil) then 1511 | begin 1512 | LCurrent := LCurrent[LArrayPart]; 1513 | end 1514 | else 1515 | begin 1516 | // Object part doesn't exist, return null 1517 | Result := TEasyJson.Create(TJSONNull.Create, LCurrent, ejOwned); 1518 | Result.FOriginalParent := Self; 1519 | Result.FOriginalKey := APath; 1520 | Exit(AddChild(Result)); 1521 | end; 1522 | end; 1523 | 1524 | // Now access the array index 1525 | if (LCurrent.FJsonValue is TJSONArray) and 1526 | (LArrayIndex >= 0) and 1527 | (LArrayIndex < TJSONArray(LCurrent.FJsonValue).Count) then 1528 | begin 1529 | LCurrent := LCurrent[LArrayIndex]; 1530 | end 1531 | else 1532 | begin 1533 | // Array index out of bounds, return null 1534 | Result := TEasyJson.Create(TJSONNull.Create, LCurrent, ejOwned); 1535 | Result.FOriginalParent := Self; 1536 | Result.FOriginalKey := APath; 1537 | Exit(AddChild(Result)); 1538 | end; 1539 | end 1540 | else 1541 | begin 1542 | // Simple object property access 1543 | if (LCurrent.FJsonValue is TJSONObject) and 1544 | (TJSONObject(LCurrent.FJsonValue).GetValue(LPart) <> nil) then 1545 | begin 1546 | LChild := TEasyJson.Create(TJSONObject(LCurrent.FJsonValue).GetValue(LPart), LCurrent, ejReference); 1547 | LChild.FOriginalParent := LCurrent; 1548 | LChild.FOriginalKey := LPart; 1549 | LCurrent := AddChild(LChild); 1550 | end 1551 | else 1552 | begin 1553 | // Property doesn't exist, return null 1554 | Result := TEasyJson.Create(TJSONNull.Create, LCurrent, ejOwned); 1555 | Result.FOriginalParent := Self; 1556 | Result.FOriginalKey := APath; 1557 | Exit(AddChild(Result)); 1558 | end; 1559 | end; 1560 | end; 1561 | 1562 | // Set up the direct reference flag 1563 | LCurrent.FIsDirectReference := True; 1564 | 1565 | // Return the final node 1566 | Result := LCurrent; 1567 | end; 1568 | 1569 | procedure TEasyJson.SetValueByPath(const APath: string; const AJson: TEasyJson); 1570 | var 1571 | LParentPath: string; 1572 | LLastDot, LLastBracketOpen, LLastBracketClose: Integer; 1573 | LKey: string; 1574 | LIndex: Integer; 1575 | LParent: TEasyJson; 1576 | begin 1577 | // Find the last segment of the path 1578 | LLastDot := LastDelimiter('.', APath); 1579 | LLastBracketOpen := LastDelimiter('[', APath); 1580 | LLastBracketClose := LastDelimiter(']', APath); 1581 | 1582 | if (LLastBracketOpen > LLastDot) and (LLastBracketClose > LLastBracketOpen) then 1583 | begin 1584 | // Last segment is an array index 1585 | LParentPath := Copy(APath, 1, LLastBracketOpen - 1); 1586 | if not TryStrToInt(Copy(APath, LLastBracketOpen + 1, LLastBracketClose - LLastBracketOpen - 1), LIndex) then 1587 | Exit; // Invalid index 1588 | 1589 | if HasPath(LParentPath) then 1590 | begin 1591 | LParent := GetValueByPath(LParentPath); 1592 | if LParent.FJsonValue is TJSONArray then 1593 | LParent.Put(LIndex, AJson); 1594 | end; 1595 | end 1596 | else if LLastDot > 0 then 1597 | begin 1598 | // Last segment is an object property 1599 | LParentPath := Copy(APath, 1, LLastDot - 1); 1600 | LKey := Copy(APath, LLastDot + 1, Length(APath)); 1601 | 1602 | if HasPath(LParentPath) then 1603 | begin 1604 | LParent := GetValueByPath(LParentPath); 1605 | if LParent.FJsonValue is TJSONObject then 1606 | LParent.Put(LKey, AJson); 1607 | end; 1608 | end 1609 | else 1610 | begin 1611 | // Path is just a direct property 1612 | if FJsonValue is TJSONObject then 1613 | Put(APath, AJson); 1614 | end; 1615 | end; 1616 | 1617 | constructor TEasyJson.Create(); 1618 | begin 1619 | inherited Create(); 1620 | 1621 | FJsonValue := TJSONObject.Create(); 1622 | FParent := nil; 1623 | FOwnership := ejOwned; 1624 | FChildren := nil; 1625 | FOriginalKey := ''; 1626 | FOriginalParent := nil; 1627 | FIsDirectReference := False; 1628 | end; 1629 | 1630 | constructor TEasyJson.Create(const AJson: string); 1631 | var 1632 | LParsedValue: TJSONValue; 1633 | begin 1634 | inherited Create(); 1635 | 1636 | LParsedValue := TJSONObject.ParseJSONValue(AJson); 1637 | if LParsedValue <> nil then 1638 | FJsonValue := LParsedValue 1639 | else 1640 | FJsonValue := TJSONObject.Create(); 1641 | 1642 | FParent := nil; 1643 | FOwnership := ejOwned; 1644 | FChildren := nil; 1645 | FOriginalParent := nil; 1646 | FOriginalKey := ''; 1647 | FIsDirectReference := False; 1648 | end; 1649 | 1650 | constructor TEasyJson.Create(const AJsonValue: TJSONValue; AOwnership: TejValueOwnership); 1651 | begin 1652 | inherited Create(); 1653 | 1654 | FJsonValue := AJsonValue; 1655 | FParent := nil; 1656 | FOwnership := AOwnership; 1657 | FChildren := nil; 1658 | FOriginalParent := nil; 1659 | FOriginalKey := ''; 1660 | FIsDirectReference := False; 1661 | end; 1662 | 1663 | constructor TEasyJson.Create(const AJsonValue: TJSONValue; AParent: TEasyJson; AOwnership: TejValueOwnership); 1664 | begin 1665 | inherited Create(); 1666 | 1667 | FJsonValue := AJsonValue; 1668 | FParent := AParent; 1669 | FOwnership := AOwnership; 1670 | FChildren := nil; 1671 | FOriginalParent := nil; 1672 | FOriginalKey := ''; 1673 | FIsDirectReference := False; 1674 | end; 1675 | 1676 | destructor TEasyJson.Destroy(); 1677 | begin 1678 | Clean(); 1679 | 1680 | inherited; 1681 | end; 1682 | 1683 | function TEasyJson.LoadFromFile(const AFilename: string): Boolean; 1684 | var 1685 | LFilename: string; 1686 | LText: string; 1687 | LJson: TJSONValue; 1688 | begin 1689 | try 1690 | Result := False; 1691 | 1692 | if AFilename.IsEmpty then Exit; 1693 | 1694 | LFilename := TPath.ChangeExtension(AFilename, 'json'); 1695 | if not TFile.Exists(LFilename) then Exit; 1696 | 1697 | LText := TFile.ReadAllText(LFilename, TEncoding.UTF8); 1698 | if LText.IsEmpty then Exit; 1699 | 1700 | LJson := TJSONObject.ParseJSONValue(LText); 1701 | if not Assigned(LJson) then Exit; 1702 | 1703 | Clean(); 1704 | 1705 | FJsonValue := LJson; 1706 | 1707 | Result := True; 1708 | except 1709 | on E: Exception do 1710 | begin 1711 | Result := False; 1712 | end; 1713 | end; 1714 | end; 1715 | 1716 | function TEasyJson.SaveToFile(const AFilename: string): Boolean; 1717 | var 1718 | LFilename: string; 1719 | LText: string; 1720 | begin 1721 | try 1722 | Result := False; 1723 | if AFilename.IsEmpty then Exit; 1724 | 1725 | LFilename := TPath.ChangeExtension(AFilename, 'json'); 1726 | 1727 | LText := Format(2); 1728 | 1729 | TFile.WriteAllText(LFilename, LText, TEncoding.UTF8); 1730 | 1731 | Result := TFile.Exists(LFilename); 1732 | except 1733 | on E: Exception do 1734 | begin 1735 | Result := False; 1736 | end; 1737 | end; 1738 | 1739 | end; 1740 | 1741 | function TEasyJson.HasPath(const APath: string): Boolean; 1742 | var 1743 | LPathParts: TArray; 1744 | LCurrent: TEasyJson; 1745 | LPart: string; 1746 | LArrayIndex: Integer; 1747 | LArrayPart: string; 1748 | LOpenBracket, LCloseBracket: Integer; 1749 | LIsArrayAccess: Boolean; 1750 | begin 1751 | if Trim(APath) = '' then 1752 | Exit(True); 1753 | 1754 | LPathParts := APath.Split(['.']); 1755 | LCurrent := Self; 1756 | 1757 | for LPart in LPathParts do 1758 | begin 1759 | if LPart = '' then 1760 | Continue; 1761 | 1762 | // Check if this part contains array access [n] 1763 | LOpenBracket := Pos('[', LPart); 1764 | LCloseBracket := Pos(']', LPart); 1765 | LIsArrayAccess := (LOpenBracket > 0) and (LCloseBracket > LOpenBracket); 1766 | 1767 | if LIsArrayAccess then 1768 | begin 1769 | // Extract the object part and array index 1770 | LArrayPart := Copy(LPart, 1, LOpenBracket - 1); 1771 | if not TryStrToInt(Copy(LPart, LOpenBracket + 1, LCloseBracket - LOpenBracket - 1), LArrayIndex) then 1772 | Exit(False); // Invalid array index 1773 | 1774 | // If we have an object part, navigate to it first 1775 | if LArrayPart <> '' then 1776 | begin 1777 | if (LCurrent.FJsonValue is TJSONObject) and 1778 | (TJSONObject(LCurrent.FJsonValue).GetValue(LArrayPart) <> nil) then 1779 | begin 1780 | LCurrent := LCurrent[LArrayPart]; 1781 | end 1782 | else 1783 | Exit(False); // Object part doesn't exist 1784 | end; 1785 | 1786 | // Now check the array index 1787 | if (LCurrent.FJsonValue is TJSONArray) and 1788 | (LArrayIndex >= 0) and 1789 | (LArrayIndex < TJSONArray(LCurrent.FJsonValue).Count) then 1790 | begin 1791 | LCurrent := LCurrent[LArrayIndex]; 1792 | end 1793 | else 1794 | Exit(False); // Array index out of bounds 1795 | end 1796 | else 1797 | begin 1798 | // Simple object property access 1799 | if (LCurrent.FJsonValue is TJSONObject) and 1800 | (TJSONObject(LCurrent.FJsonValue).GetValue(LPart) <> nil) then 1801 | begin 1802 | LCurrent := LCurrent[LPart]; 1803 | end 1804 | else 1805 | Exit(False); // Property doesn't exist 1806 | end; 1807 | end; 1808 | 1809 | // If we got here, the path exists 1810 | Result := True; 1811 | end; 1812 | 1813 | procedure TEasyJson.Clear(); 1814 | begin 1815 | Clean(); 1816 | 1817 | FJsonValue := TJSONObject.Create(); 1818 | end; 1819 | 1820 | function TEasyJson.GetValue(const AKeyOrIndex: Variant): TEasyJson; 1821 | var 1822 | LObj: TJSONObject; 1823 | LArray: TJSONArray; 1824 | LValue: TJSONValue; 1825 | LResult: TEasyJson; 1826 | begin 1827 | if VarIsStr(AKeyOrIndex) then 1828 | begin 1829 | // Access by string key 1830 | LObj := AsObject(); 1831 | if (LObj <> nil) and LObj.TryGetValue(string(AKeyOrIndex), LValue) then 1832 | begin 1833 | LResult := TEasyJson.Create(LValue, Self, ejReference); 1834 | // Set original parent and key for tracking 1835 | LResult.FOriginalParent := Self; 1836 | LResult.FOriginalKey := string(AKeyOrIndex); 1837 | // Set direct reference flag 1838 | LResult.FIsDirectReference := True; 1839 | Result := AddChild(LResult); 1840 | end 1841 | else 1842 | begin 1843 | LResult := TEasyJson.Create(TJSONNull.Create, Self, ejOwned); 1844 | Result := AddChild(LResult); 1845 | end; 1846 | end 1847 | else if VarType(AKeyOrIndex) in [varSmallint, varInteger, varByte, varWord, varLongWord, varInt64] then 1848 | begin 1849 | // Access by numeric index 1850 | LArray := AsArray(); 1851 | if (LArray <> nil) and (Integer(AKeyOrIndex) >= 0) and (Integer(AKeyOrIndex) < LArray.Count) then 1852 | begin 1853 | LResult := TEasyJson.Create(LArray.Items[Integer(AKeyOrIndex)], Self, ejReference); 1854 | // Set original parent and key for tracking 1855 | LResult.FOriginalParent := Self; 1856 | LResult.FOriginalKey := IntToStr(Integer(AKeyOrIndex)); 1857 | // Set direct reference flag 1858 | LResult.FIsDirectReference := True; 1859 | Result := AddChild(LResult); 1860 | end 1861 | else 1862 | begin 1863 | LResult := TEasyJson.Create(TJSONNull.Create(), Self, ejOwned); 1864 | Result := AddChild(LResult); 1865 | end; 1866 | end 1867 | else 1868 | begin 1869 | // Invalid index type 1870 | LResult := TEasyJson.Create(TJSONNull.Create(), Self, ejOwned); 1871 | Result := AddChild(LResult); 1872 | end; 1873 | end; 1874 | 1875 | function TEasyJson.CreateJsonValue(const AValue: Variant): TJSONValue; 1876 | begin 1877 | if VarIsNull(AValue) or VarIsEmpty(AValue) then 1878 | Result := TJSONNull.Create 1879 | else if VarType(AValue) in [varSmallint, varInteger, varByte, varWord, varLongWord, varInt64] then 1880 | Result := TJSONNumber.Create(Integer(AValue)) 1881 | else if VarType(AValue) in [varSingle, varDouble, varCurrency] then 1882 | Result := TJSONNumber.Create(Double(AValue)) 1883 | else if VarType(AValue) = varBoolean then 1884 | begin 1885 | if Boolean(AValue) then 1886 | Result := TJSONTrue.Create() 1887 | else 1888 | Result := TJSONFalse.Create(); 1889 | end 1890 | else 1891 | Result := TJSONString.Create(VarToStr(AValue)); 1892 | end; 1893 | 1894 | procedure TEasyJson.SafeAddPair(const AObj: TJSONObject; const AName: string; AValue: TJSONValue); 1895 | var 1896 | I: Integer; 1897 | begin 1898 | if AObj = nil then 1899 | Exit; 1900 | 1901 | // Look for existing pair with same name 1902 | for I := 0 to AObj.Count - 1 do 1903 | begin 1904 | if AObj.Pairs[I].JsonString.Value = AName then 1905 | begin 1906 | // Remove the existing pair and free it 1907 | AObj.RemovePair(AName).Free(); 1908 | Break; 1909 | end; 1910 | end; 1911 | 1912 | // Add the new pair 1913 | AObj.AddPair(AName, AValue); 1914 | end; 1915 | 1916 | function TEasyJson.GetOrCreateArray(const AArray: TJSONArray; AIndex: Integer): TJSONArray; 1917 | var 1918 | I: Integer; 1919 | begin 1920 | Result := AArray; 1921 | 1922 | // Make sure we have enough elements 1923 | if AIndex >= AArray.Count then 1924 | begin 1925 | for I := AArray.Count to AIndex do 1926 | begin 1927 | AArray.AddElement(TJSONNull.Create); 1928 | end; 1929 | end; 1930 | end; 1931 | 1932 | function TEasyJson.AddChild(const AChild: TEasyJson): TEasyJson; 1933 | begin 1934 | if AChild <> nil then 1935 | begin 1936 | // Initialize the children list if needed 1937 | if FChildren = nil then 1938 | FChildren := TObjectList.Create(True); 1939 | 1940 | // Add the child to our tracking list 1941 | FChildren.Add(AChild); 1942 | end; 1943 | 1944 | Result := AChild; 1945 | end; 1946 | 1947 | function TEasyJson.Put(const AKey: string; const AValue: Variant): TEasyJson; 1948 | var 1949 | LObj, LParentObj: TJSONObject; 1950 | LParentArray: TJSONArray; 1951 | LValue: TJSONValue; 1952 | LArrIndex: Integer; 1953 | begin 1954 | LObj := AsObject(); 1955 | if LObj <> nil then 1956 | begin 1957 | LValue := CreateJsonValue(AValue); 1958 | SafeAddPair(LObj, AKey, LValue); 1959 | 1960 | // If this is a direct reference, no need to update the original parent 1961 | // as we're directly modifying the object in the parent structure 1962 | if not FIsDirectReference then 1963 | begin 1964 | // Update original parent if this is a reference 1965 | if (FOriginalParent <> nil) and (FOriginalKey <> '') then 1966 | begin 1967 | if FOriginalParent.FJsonValue is TJSONObject then 1968 | begin 1969 | LParentObj := FOriginalParent.AsObject(); 1970 | if LParentObj <> nil then 1971 | begin 1972 | // Replace the value in the parent - this is safer but may be unnecessary for direct references 1973 | if LParentObj.GetValue(FOriginalKey) <> FJsonValue then 1974 | begin 1975 | // Only replace if the reference has changed 1976 | LParentObj.RemovePair(FOriginalKey).Free; 1977 | LParentObj.AddPair(FOriginalKey, FJsonValue.Clone as TJSONValue); 1978 | end; 1979 | end; 1980 | end 1981 | else if FOriginalParent.FJsonValue is TJSONArray then 1982 | begin 1983 | LParentArray := FOriginalParent.AsArray(); 1984 | if LParentArray <> nil then 1985 | begin 1986 | if TryStrToInt(FOriginalKey, LArrIndex) then 1987 | begin 1988 | // Replace the value in the parent array 1989 | if (LArrIndex >= 0) and (LArrIndex < LParentArray.Count) then 1990 | begin 1991 | // Check if we need to replace it 1992 | if LParentArray.Items[LArrIndex] <> FJsonValue then 1993 | begin 1994 | LParentArray.Items[LArrIndex].Free; 1995 | LParentArray.Remove(LArrIndex); 1996 | LParentArray.AddElement(FJsonValue.Clone as TJSONValue); 1997 | end; 1998 | end; 1999 | end; 2000 | end; 2001 | end; 2002 | end; 2003 | end; 2004 | end; 2005 | Result := Self; 2006 | end; 2007 | 2008 | function TEasyJson.Put(const AKey: string; const AJson: TEasyJson): TEasyJson; 2009 | var 2010 | LObj, LParentObj: TJSONObject; 2011 | LParentArray: TJSONArray; 2012 | LClone: TJSONValue; 2013 | LArrIndex: Integer; 2014 | begin 2015 | LObj := AsObject(); 2016 | if (LObj <> nil) and (AJson <> nil) and (AJson.FJsonValue <> nil) then 2017 | begin 2018 | LClone := AJson.FJsonValue.Clone as TJSONValue; 2019 | SafeAddPair(LObj, AKey, LClone); 2020 | 2021 | // If this is a direct reference, no need to update the original parent 2022 | if not FIsDirectReference then 2023 | begin 2024 | // Update original parent if this is a reference 2025 | if (FOriginalParent <> nil) and (FOriginalKey <> '') then 2026 | begin 2027 | if FOriginalParent.FJsonValue is TJSONObject then 2028 | begin 2029 | LParentObj := FOriginalParent.AsObject(); 2030 | if LParentObj <> nil then 2031 | begin 2032 | // Replace the value in the parent 2033 | if LParentObj.GetValue(FOriginalKey) <> FJsonValue then 2034 | begin 2035 | LParentObj.RemovePair(FOriginalKey).Free; 2036 | LParentObj.AddPair(FOriginalKey, FJsonValue.Clone as TJSONValue); 2037 | end; 2038 | end; 2039 | end 2040 | else if FOriginalParent.FJsonValue is TJSONArray then 2041 | begin 2042 | LParentArray := FOriginalParent.AsArray(); 2043 | if LParentArray <> nil then 2044 | begin 2045 | if TryStrToInt(FOriginalKey, LArrIndex) then 2046 | begin 2047 | // Replace the value in the parent array 2048 | if (LArrIndex >= 0) and (LArrIndex < LParentArray.Count) then 2049 | begin 2050 | if LParentArray.Items[LArrIndex] <> FJsonValue then 2051 | begin 2052 | LParentArray.Items[LArrIndex].Free(); 2053 | LParentArray.Remove(LArrIndex); 2054 | LParentArray.AddElement(FJsonValue.Clone as TJSONValue); 2055 | end; 2056 | end; 2057 | end; 2058 | end; 2059 | end; 2060 | end; 2061 | end; 2062 | end; 2063 | Result := Self; 2064 | end; 2065 | 2066 | function TEasyJson.Put(const AKey: string; const AJSONValue: TJSONValue): TEasyJson; 2067 | var 2068 | LObj, LParentObj: TJSONObject; 2069 | LParentArray: TJSONArray; 2070 | LClone: TJSONValue; 2071 | LArrIndex: Integer; 2072 | begin 2073 | LObj := AsObject(); 2074 | if (LObj <> nil) and (AJSONValue <> nil) then 2075 | begin 2076 | LClone := AJSONValue.Clone as TJSONValue; 2077 | SafeAddPair(LObj, AKey, LClone); 2078 | 2079 | // If this is a direct reference, no need to update the original parent 2080 | if not FIsDirectReference then 2081 | begin 2082 | // Update original parent if this is a reference 2083 | if (FOriginalParent <> nil) and (FOriginalKey <> '') then 2084 | begin 2085 | if FOriginalParent.FJsonValue is TJSONObject then 2086 | begin 2087 | LParentObj := FOriginalParent.AsObject; 2088 | if LParentObj <> nil then 2089 | begin 2090 | // Replace the value in the parent 2091 | if LParentObj.GetValue(FOriginalKey) <> FJsonValue then 2092 | begin 2093 | LParentObj.RemovePair(FOriginalKey).Free; 2094 | LParentObj.AddPair(FOriginalKey, FJsonValue.Clone as TJSONValue); 2095 | end; 2096 | end; 2097 | end 2098 | else if FOriginalParent.FJsonValue is TJSONArray then 2099 | begin 2100 | LParentArray := FOriginalParent.AsArray(); 2101 | if LParentArray <> nil then 2102 | begin 2103 | if TryStrToInt(FOriginalKey, LArrIndex) then 2104 | begin 2105 | // Replace the value in the parent array 2106 | if (LArrIndex >= 0) and (LArrIndex < LParentArray.Count) then 2107 | begin 2108 | if LParentArray.Items[LArrIndex] <> FJsonValue then 2109 | begin 2110 | LParentArray.Items[LArrIndex].Free(); 2111 | LParentArray.Remove(LArrIndex); 2112 | LParentArray.AddElement(FJsonValue.Clone as TJSONValue); 2113 | end; 2114 | end; 2115 | end; 2116 | end; 2117 | end; 2118 | end; 2119 | end; 2120 | end; 2121 | Result := Self; 2122 | end; 2123 | 2124 | function TEasyJson.Put(const AIndex: Integer; const AValue: Variant): TEasyJson; 2125 | var 2126 | LArray, LParentArray: TJSONArray; 2127 | LParentObj: TJSONObject; 2128 | LValue: TJSONValue; 2129 | LArrIndex: Integer; 2130 | begin 2131 | LArray := AsArray(); 2132 | if LArray <> nil then 2133 | begin 2134 | // Ensure array has enough elements 2135 | GetOrCreateArray(LArray, AIndex); 2136 | 2137 | // Create the new value 2138 | LValue := CreateJsonValue(AValue); 2139 | 2140 | // Replace the element 2141 | if (AIndex >= 0) and (AIndex < LArray.Count) then 2142 | begin 2143 | // Free the old value 2144 | LArray.Items[AIndex].Free(); 2145 | 2146 | // Replace it - direct assignment doesn't work, so we need to remove and add 2147 | LArray.Remove(AIndex); 2148 | LArray.AddElement(LValue); 2149 | 2150 | // If this is a direct reference, no need to update the original parent 2151 | if not FIsDirectReference then 2152 | begin 2153 | // Update original parent if this is a reference 2154 | if (FOriginalParent <> nil) and (FOriginalKey <> '') then 2155 | begin 2156 | if FOriginalParent.FJsonValue is TJSONObject then 2157 | begin 2158 | LParentObj := FOriginalParent.AsObject(); 2159 | if LParentObj <> nil then 2160 | begin 2161 | // Replace the value in the parent 2162 | if LParentObj.GetValue(FOriginalKey) <> FJsonValue then 2163 | begin 2164 | LParentObj.RemovePair(FOriginalKey).Free; 2165 | LParentObj.AddPair(FOriginalKey, FJsonValue.Clone as TJSONValue); 2166 | end; 2167 | end; 2168 | end 2169 | else if FOriginalParent.FJsonValue is TJSONArray then 2170 | begin 2171 | LParentArray := FOriginalParent.AsArray(); 2172 | if LParentArray <> nil then 2173 | begin 2174 | if TryStrToInt(FOriginalKey, LArrIndex) then 2175 | begin 2176 | // Replace the value in the parent array 2177 | if (LArrIndex >= 0) and (LArrIndex < LParentArray.Count) then 2178 | begin 2179 | if LParentArray.Items[LArrIndex] <> FJsonValue then 2180 | begin 2181 | LParentArray.Items[LArrIndex].Free(); 2182 | LParentArray.Remove(LArrIndex); 2183 | LParentArray.AddElement(FJsonValue.Clone as TJSONValue); 2184 | end; 2185 | end; 2186 | end; 2187 | end; 2188 | end; 2189 | end; 2190 | end; 2191 | end; 2192 | end; 2193 | Result := Self; 2194 | end; 2195 | 2196 | function TEasyJson.Put(const AIndex: Integer; const AJson: TEasyJson): TEasyJson; 2197 | var 2198 | LArray, LParentArray: TJSONArray; 2199 | ParentObj: TJSONObject; 2200 | LClone: TJSONValue; 2201 | LArrIndex: Integer; 2202 | begin 2203 | LArray := AsArray(); 2204 | if (LArray <> nil) and (AJson <> nil) and (AJson.FJsonValue <> nil) then 2205 | begin 2206 | // Ensure array has enough elements 2207 | GetOrCreateArray(LArray, AIndex); 2208 | 2209 | // Clone the value 2210 | LClone := AJson.FJsonValue.Clone as TJSONValue; 2211 | 2212 | // Replace the element 2213 | if (AIndex >= 0) and (AIndex < LArray.Count) then 2214 | begin 2215 | // Free the old value 2216 | LArray.Items[AIndex].Free(); 2217 | 2218 | // Replace it - direct assignment doesn't work, so we need to remove and add 2219 | LArray.Remove(AIndex); 2220 | LArray.AddElement(LClone); 2221 | 2222 | // If this is a direct reference, no need to update the original parent 2223 | if not FIsDirectReference then 2224 | begin 2225 | // Update original parent if this is a reference 2226 | if (FOriginalParent <> nil) and (FOriginalKey <> '') then 2227 | begin 2228 | if FOriginalParent.FJsonValue is TJSONObject then 2229 | begin 2230 | ParentObj := FOriginalParent.AsObject(); 2231 | if ParentObj <> nil then 2232 | begin 2233 | // Replace the value in the parent 2234 | if ParentObj.GetValue(FOriginalKey) <> FJsonValue then 2235 | begin 2236 | ParentObj.RemovePair(FOriginalKey).Free; 2237 | ParentObj.AddPair(FOriginalKey, FJsonValue.Clone as TJSONValue); 2238 | end; 2239 | end; 2240 | end 2241 | else if FOriginalParent.FJsonValue is TJSONArray then 2242 | begin 2243 | LParentArray := FOriginalParent.AsArray(); 2244 | if LParentArray <> nil then 2245 | begin 2246 | if TryStrToInt(FOriginalKey, LArrIndex) then 2247 | begin 2248 | // Replace the value in the parent array 2249 | if (LArrIndex >= 0) and (LArrIndex < LParentArray.Count) then 2250 | begin 2251 | if LParentArray.Items[LArrIndex] <> FJsonValue then 2252 | begin 2253 | LParentArray.Items[LArrIndex].Free(); 2254 | LParentArray.Remove(LArrIndex); 2255 | LParentArray.AddElement(FJsonValue.Clone as TJSONValue); 2256 | end; 2257 | end; 2258 | end; 2259 | end; 2260 | end; 2261 | end; 2262 | end; 2263 | end; 2264 | end; 2265 | Result := Self; 2266 | end; 2267 | 2268 | function TEasyJson.Put(const AIndex: Integer; const AJSONValue: TJSONValue): TEasyJson; 2269 | var 2270 | LArray, LParentArray: TJSONArray; 2271 | LParentObj: TJSONObject; 2272 | LClone: TJSONValue; 2273 | LArrIndex: Integer; 2274 | LNewArray: TJSONArray; 2275 | I: Integer; 2276 | begin 2277 | LArray := AsArray(); 2278 | if (LArray <> nil) and (AJSONValue <> nil) then 2279 | begin 2280 | // Ensure array has enough elements 2281 | GetOrCreateArray(LArray, AIndex); 2282 | 2283 | // Clone the JSON value 2284 | LClone := AJSONValue.Clone as TJSONValue; 2285 | 2286 | // Replace the element 2287 | if (AIndex >= 0) and (AIndex < LArray.Count) then 2288 | begin 2289 | // Create a new array with the updated element at the correct position 2290 | LNewArray := TJSONArray.Create(); 2291 | try 2292 | for I := 0 to LArray.Count - 1 do 2293 | begin 2294 | if I = AIndex then 2295 | LNewArray.AddElement(LClone) 2296 | else 2297 | LNewArray.AddElement(LArray.Items[I].Clone as TJSONValue); 2298 | end; 2299 | 2300 | // Replace the original array with the new one 2301 | if FJsonValue = LArray then 2302 | begin 2303 | FJsonValue.Free; 2304 | FJsonValue := LNewArray; 2305 | 2306 | // If this is a direct reference, no need to update the original parent 2307 | if not FIsDirectReference then 2308 | begin 2309 | // Update original parent if this is a reference 2310 | if (FOriginalParent <> nil) and (FOriginalKey <> '') then 2311 | begin 2312 | if FOriginalParent.FJsonValue is TJSONObject then 2313 | begin 2314 | LParentObj := FOriginalParent.AsObject(); 2315 | if LParentObj <> nil then 2316 | begin 2317 | // Replace the value in the parent 2318 | if LParentObj.GetValue(FOriginalKey) <> FJsonValue then 2319 | begin 2320 | LParentObj.RemovePair(FOriginalKey).Free; 2321 | LParentObj.AddPair(FOriginalKey, FJsonValue.Clone as TJSONValue); 2322 | end; 2323 | end; 2324 | end 2325 | else if FOriginalParent.FJsonValue is TJSONArray then 2326 | begin 2327 | LParentArray := FOriginalParent.AsArray(); 2328 | if LParentArray <> nil then 2329 | begin 2330 | if TryStrToInt(FOriginalKey, LArrIndex) then 2331 | begin 2332 | // Replace the value in the parent array 2333 | if (LArrIndex >= 0) and (LArrIndex < LParentArray.Count) then 2334 | begin 2335 | if LParentArray.Items[LArrIndex] <> FJsonValue then 2336 | begin 2337 | LParentArray.Items[LArrIndex].Free(); 2338 | LParentArray.Remove(LArrIndex); 2339 | LParentArray.AddElement(FJsonValue.Clone as TJSONValue); 2340 | end; 2341 | end; 2342 | end; 2343 | end; 2344 | end; 2345 | end; 2346 | end; 2347 | end 2348 | else 2349 | begin 2350 | // This is a complex case - we'd need to find and replace the array in its parent 2351 | LNewArray.Free(); 2352 | LClone.Free; 2353 | end; 2354 | except 2355 | LNewArray.Free(); 2356 | LClone.Free(); 2357 | raise; 2358 | end; 2359 | end 2360 | else 2361 | begin 2362 | LClone.Free(); // Clean up if we didn't use it 2363 | end; 2364 | end; 2365 | Result := Self; 2366 | end; 2367 | 2368 | function TEasyJson.Add(const AKey: string; const AValue: Variant): TEasyJson; 2369 | var 2370 | LObj: TJSONObject; 2371 | LValue: TJSONValue; 2372 | begin 2373 | LObj := AsObject(); 2374 | if LObj <> nil then 2375 | begin 2376 | LValue := CreateJsonValue(AValue); 2377 | LObj.AddPair(AKey, LValue); 2378 | end; 2379 | Result := Self; 2380 | end; 2381 | 2382 | function TEasyJson.Add(const AKey: string; const AJson: TEasyJson): TEasyJson; 2383 | begin 2384 | if (AJson <> nil) and (AJson.FJsonValue <> nil) then 2385 | Add(AKey, AJson.FJsonValue.Clone as TJSONValue) 2386 | else 2387 | Add(AKey, TJSONNull.Create); 2388 | 2389 | Result := Self; 2390 | end; 2391 | 2392 | function TEasyJson.Add(const AKey: string; const AJSONValue: TJSONValue): TEasyJson; 2393 | var 2394 | LObj: TJSONObject; 2395 | LClone: TJSONValue; 2396 | begin 2397 | LObj := AsObject; 2398 | if (LObj <> nil) and (AJSONValue <> nil) then 2399 | begin 2400 | LClone := AJSONValue.Clone as TJSONValue; 2401 | LObj.AddPair(AKey, LClone); 2402 | end; 2403 | Result := Self; 2404 | end; 2405 | 2406 | function TEasyJson.Add(const AKey: string; const AObject: TJSONObject): TEasyJson; 2407 | begin 2408 | if AObject <> nil then 2409 | Add(AKey, AObject as TJSONValue) 2410 | else 2411 | Add(AKey, TJSONNull.Create); 2412 | 2413 | Result := Self; 2414 | end; 2415 | 2416 | function TEasyJson.Add(const AKey: string; const AnArray: TJSONArray): TEasyJson; 2417 | begin 2418 | if AnArray <> nil then 2419 | Add(AKey, AnArray as TJSONValue) 2420 | else 2421 | Add(AKey, TJSONNull.Create); 2422 | 2423 | Result := Self; 2424 | end; 2425 | 2426 | function TEasyJson.AddObject(): TEasyJson; 2427 | var 2428 | LObj: TJSONObject; 2429 | LArray: TJSONArray; 2430 | LResult: TEasyJson; 2431 | begin 2432 | LObj := TJSONObject.Create(); 2433 | 2434 | if FJsonValue = nil then 2435 | begin 2436 | FJsonValue := LObj; 2437 | Result := Self; 2438 | end 2439 | else if FJsonValue is TJSONArray then 2440 | begin 2441 | LArray := AsArray(); 2442 | LArray.AddElement(LObj); 2443 | 2444 | // Create a new TEasyJson for the child and track it 2445 | LResult := TEasyJson.Create(LObj, Self, ejReference); 2446 | Result := AddChild(LResult); 2447 | end 2448 | else 2449 | begin 2450 | LObj.Free; 2451 | Result := Self; 2452 | end; 2453 | end; 2454 | 2455 | function TEasyJson.AddObject(const AKey: string): TEasyJson; 2456 | var 2457 | LObj: TJSONObject; 2458 | LParentObj: TJSONObject; 2459 | LResult: TEasyJson; 2460 | begin 2461 | LParentObj := AsObject(); 2462 | if LParentObj <> nil then 2463 | begin 2464 | LObj := TJSONObject.Create; 2465 | LParentObj.AddPair(AKey, LObj); 2466 | 2467 | // Create a new TEasyJson for the child and track it 2468 | LResult := TEasyJson.Create(LObj, Self, ejReference); 2469 | Result := AddChild(LResult); 2470 | end 2471 | else 2472 | Result := Self; 2473 | end; 2474 | 2475 | function TEasyJson.AddObject(const AKey: string; const AFunc: TFunc): TEasyJson; 2476 | var 2477 | LObj: TJSONObject; 2478 | LParentObj: TJSONObject; 2479 | LChildJson: TEasyJson; 2480 | begin 2481 | LParentObj := AsObject(); 2482 | if LParentObj <> nil then 2483 | begin 2484 | LObj := TJSONObject.Create(); 2485 | 2486 | // Create a child TEasyJson that we own 2487 | LChildJson := TEasyJson.Create(LObj, ejOwned); 2488 | 2489 | // Call the function to populate the object 2490 | if Assigned(AFunc) then 2491 | AFunc(LChildJson); 2492 | 2493 | // Transfer ownership of the JSON value to the parent 2494 | LChildJson.FOwnership := ejReference; 2495 | 2496 | // Add the object to the parent 2497 | LParentObj.AddPair(AKey, LObj); 2498 | 2499 | // Free the child wrapper but not the JSON object 2500 | LChildJson.Free(); 2501 | end; 2502 | 2503 | Result := Self; 2504 | end; 2505 | 2506 | function TEasyJson.AddObject(const AFunc: TFunc): TEasyJson; 2507 | var 2508 | LObj: TJSONObject; 2509 | LArray: TJSONArray; 2510 | LChildJson: TEasyJson; 2511 | begin 2512 | LObj := TJSONObject.Create(); 2513 | 2514 | // Create a child TEasyJson that we own 2515 | LChildJson := TEasyJson.Create(LObj, ejOwned); 2516 | 2517 | // Call the function to populate the object 2518 | if Assigned(AFunc) then 2519 | AFunc(LChildJson); 2520 | 2521 | if FJsonValue is TJSONArray then 2522 | begin 2523 | // Add to array 2524 | LArray := AsArray(); 2525 | LArray.AddElement(LObj); 2526 | 2527 | // Transfer ownership 2528 | LChildJson.FOwnership := ejReference; 2529 | 2530 | // Free the wrapper but not the JSON object 2531 | LChildJson.Free(); 2532 | 2533 | Result := Self; 2534 | end 2535 | else if FJsonValue = nil then 2536 | begin 2537 | // This is the root 2538 | FJsonValue := LObj; 2539 | 2540 | // Transfer ownership 2541 | LChildJson.FOwnership := ejReference; 2542 | 2543 | // Free the wrapper but not the JSON object 2544 | LChildJson.Free(); 2545 | 2546 | Result := Self; 2547 | end 2548 | else 2549 | begin 2550 | // Invalid case 2551 | LChildJson.Free(); 2552 | Result := Self; 2553 | end; 2554 | end; 2555 | 2556 | function TEasyJson.AddArray(): TEasyJson; 2557 | var 2558 | LArray: TJSONArray; 2559 | LParentArray: TJSONArray; 2560 | LResult: TEasyJson; 2561 | begin 2562 | LArray := TJSONArray.Create(); 2563 | 2564 | if FJsonValue = nil then 2565 | begin 2566 | FJsonValue := LArray; 2567 | Result := Self; 2568 | end 2569 | else if FJsonValue is TJSONArray then 2570 | begin 2571 | LParentArray := AsArray(); 2572 | LParentArray.AddElement(LArray); 2573 | 2574 | // Create a new TEasyJson for the child array and track it 2575 | LResult := TEasyJson.Create(LArray, Self, ejReference); 2576 | Result := AddChild(LResult); 2577 | end 2578 | else 2579 | begin 2580 | LArray.Free(); 2581 | Result := Self; 2582 | end; 2583 | end; 2584 | 2585 | function TEasyJson.AddArray(const AKey: string): TEasyJson; 2586 | var 2587 | LArray: TJSONArray; 2588 | LParentObj: TJSONObject; 2589 | LResult: TEasyJson; 2590 | begin 2591 | LParentObj := AsObject(); 2592 | if LParentObj <> nil then 2593 | begin 2594 | LArray := TJSONArray.Create(); 2595 | LParentObj.AddPair(AKey, LArray); 2596 | 2597 | // Create a new TEasyJson for the child array and track it 2598 | LResult := TEasyJson.Create(LArray, Self, ejReference); 2599 | Result := AddChild(LResult); 2600 | end 2601 | else 2602 | Result := Self; 2603 | end; 2604 | 2605 | function TEasyJson.Back(): TEasyJson; 2606 | begin 2607 | if FParent <> nil then 2608 | Result := FParent 2609 | else 2610 | Result := Self; 2611 | end; 2612 | 2613 | function TEasyJson.Root(): TEasyJson; 2614 | var 2615 | LCurrent: TEasyJson; 2616 | begin 2617 | LCurrent := Self; 2618 | while LCurrent.FParent <> nil do 2619 | LCurrent := LCurrent.FParent; 2620 | 2621 | Result := LCurrent; 2622 | end; 2623 | 2624 | function TEasyJson.Count(): Integer; 2625 | begin 2626 | if FJsonValue is TJSONArray then 2627 | Result := TJSONArray(FJsonValue).Count 2628 | else if FJsonValue is TJSONObject then 2629 | Result := TJSONObject(FJsonValue).Count 2630 | else 2631 | Result := 0; 2632 | end; 2633 | 2634 | function TEasyJson.ToString(): string; 2635 | begin 2636 | if FJsonValue <> nil then 2637 | Result := FJsonValue.ToString 2638 | else 2639 | Result := ''; 2640 | end; 2641 | 2642 | function TEasyJson.Format(const AIndentation: Integer = 4): string; 2643 | begin 2644 | if FJsonValue <> nil then 2645 | Result := FJsonValue.Format(AIndentation) 2646 | else 2647 | Result := ''; 2648 | end; 2649 | 2650 | function TEasyJson.AsString(): string; 2651 | begin 2652 | if FJsonValue is TJSONString then 2653 | Result := TJSONString(FJsonValue).Value 2654 | else if FJsonValue is TJSONNumber then 2655 | Result := TJSONNumber(FJsonValue).ToString 2656 | else if FJsonValue is TJSONTrue then 2657 | Result := 'true' 2658 | else if FJsonValue is TJSONFalse then 2659 | Result := 'false' 2660 | else if FJsonValue is TJSONNull then 2661 | Result := 'null' 2662 | else 2663 | Result := ''; 2664 | end; 2665 | 2666 | function TEasyJson.AsInt32(): Int32; 2667 | begin 2668 | if FJsonValue is TJSONNumber then 2669 | Result := Round(TJSONNumber(FJsonValue).AsDouble) 2670 | else if FJsonValue is TJSONString then 2671 | begin 2672 | if not TryStrToInt(TJSONString(FJsonValue).Value, Result) then 2673 | Result := 0; 2674 | end 2675 | else if FJsonValue is TJSONTrue then 2676 | Result := 1 2677 | else if FJsonValue is TJSONFalse then 2678 | Result := 0 2679 | else 2680 | Result := 0; 2681 | end; 2682 | 2683 | function TEasyJson.AsUInt32(): UInt32; 2684 | begin 2685 | if FJsonValue is TJSONNumber then 2686 | Result := Round(TJSONNumber(FJsonValue).AsDouble) 2687 | else if FJsonValue is TJSONString then 2688 | begin 2689 | if not TryStrToUInt(TJSONString(FJsonValue).Value, Result) then 2690 | Result := 0; 2691 | end 2692 | else if FJsonValue is TJSONTrue then 2693 | Result := 1 2694 | else if FJsonValue is TJSONFalse then 2695 | Result := 0 2696 | else 2697 | Result := 0; 2698 | end; 2699 | 2700 | function TEasyJson.AsInt64(): Int64; 2701 | begin 2702 | if FJsonValue is TJSONNumber then 2703 | Result := Round(TJSONNumber(FJsonValue).AsDouble) 2704 | else if FJsonValue is TJSONString then 2705 | begin 2706 | if not TryStrToInt64(TJSONString(FJsonValue).Value, Result) then 2707 | Result := 0; 2708 | end 2709 | else if FJsonValue is TJSONTrue then 2710 | Result := 1 2711 | else if FJsonValue is TJSONFalse then 2712 | Result := 0 2713 | else 2714 | Result := 0; 2715 | end; 2716 | 2717 | function TEasyJson.AsUInt64(): UInt64; 2718 | begin 2719 | if FJsonValue is TJSONNumber then 2720 | Result := Round(TJSONNumber(FJsonValue).AsDouble) 2721 | else if FJsonValue is TJSONString then 2722 | begin 2723 | if not TryStrToUInt64(TJSONString(FJsonValue).Value, Result) then 2724 | Result := 0; 2725 | end 2726 | else if FJsonValue is TJSONTrue then 2727 | Result := 1 2728 | else if FJsonValue is TJSONFalse then 2729 | Result := 0 2730 | else 2731 | Result := 0; 2732 | end; 2733 | 2734 | function TEasyJson.AsFloat(): Double; 2735 | begin 2736 | if FJsonValue is TJSONNumber then 2737 | Result := TJSONNumber(FJsonValue).AsDouble 2738 | else if FJsonValue is TJSONString then 2739 | begin 2740 | if not TryStrToFloat(TJSONString(FJsonValue).Value, Result) then 2741 | Result := 0; 2742 | end 2743 | else if FJsonValue is TJSONTrue then 2744 | Result := 1 2745 | else if FJsonValue is TJSONFalse then 2746 | Result := 0 2747 | else 2748 | Result := 0; 2749 | end; 2750 | 2751 | function TEasyJson.AsBoolean(): Boolean; 2752 | begin 2753 | if FJsonValue is TJSONTrue then 2754 | Result := True 2755 | else if FJsonValue is TJSONFalse then 2756 | Result := False 2757 | else if FJsonValue is TJSONNumber then 2758 | Result := TJSONNumber(FJsonValue).AsDouble <> 0 2759 | else if FJsonValue is TJSONString then 2760 | begin 2761 | if SameText(TJSONString(FJsonValue).Value, 'true') then 2762 | Result := True 2763 | else if SameText(TJSONString(FJsonValue).Value, 'false') then 2764 | Result := False 2765 | else 2766 | Result := False; 2767 | end 2768 | else 2769 | Result := False; 2770 | end; 2771 | 2772 | function TEasyJson.AsObject(): TJSONObject; 2773 | begin 2774 | if FJsonValue is TJSONObject then 2775 | Result := TJSONObject(FJsonValue) 2776 | else 2777 | Result := nil; 2778 | end; 2779 | 2780 | function TEasyJson.AsArray(): TJSONArray; 2781 | begin 2782 | if FJsonValue is TJSONArray then 2783 | Result := TJSONArray(FJsonValue) 2784 | else 2785 | Result := nil; 2786 | end; 2787 | 2788 | function TEasyJson.AsJSONValue(): TJSONValue; 2789 | begin 2790 | Result := FJsonValue; 2791 | end; 2792 | 2793 | class function TEasyJson.GetVersion(): string; 2794 | begin 2795 | Result := '1.0.0'; 2796 | end; 2797 | 2798 | end. 2799 | --------------------------------------------------------------------------------