Understanding the Synergy JSON API
The JSON API represents the state of a JSON object into Synergy format and vice versa so JSON data can be stored and transferred by your Synergy application. It consists of the following:
-
The JsonDocument class is both the entry point and master container for working with JSON data. It provides the means of parsing JSON data, and an instantiated JsonDocument owns all of the object references to the individual JsonElement objects.
-
The JsonElement class represents a single specific JSON value or structure within a JsonDocument. For example, each object, array, or value is represented as a JsonElement.
-
The JsonValueKind enumeration specifies the data type of a JSON value.
-
The Utf8JsonWriter class enables you to write UTF-8 encoded JSON text sequentially with no caching.
Using the JSON API for reading JSON data, you will start with a call to JsonDocument.Parse to process a string of data in JSON format. That will return a JsonDocument instance that acts as the container for all of the JSON data. In JSON, there is always an unnamed object, also known as the root element, wrapping the data. That root element is available from the RootElement property on the JsonDocument instance. From there, you can navigate the tree of JSON data by getting additional JsonElement objects by name through the GetProperty method, evaluating what kind of data they are through the ValueKind property, and retrieving data through the various GetDataType methods (e.g., GetBoolean, GetDecimal, etc.).
When writing JSON back out, the Utf8JsonWriter provides methods for constructing the various parts of a JSON object. There is no validation built into the writer, so you are expected to make the calls in an order that produces valid JSON.
The example below demonstrates constructing some sample JSON data with Utf8JsonWriter, parsing that output back in with JsonDocument.Parse, and writing the values back out to the screen.
Examples
import System.Text import System.Text.Json .define SAMPLE_FILE, "C:\temp\mysample.json" ; Although there is no requirement to make these properties defines/const, ; it’s always a good idea to avoid “magic” strings in code .region "Json Property Strings" .define JSON_NAMEPROP, "Name" .define JSON_SAMPLEARRAYPROP, "SampleArray" .define JSON_IDPROP, "Id" .define JSON_BOOLEANDATAPROP, "BooleanData" .define JSON_STRINGDATAPROP, "StringData" .endregion ;;; <summary> ;;; Sample program that demonstrates first writing some JSON data, ;;; then reading that data back in and displaying it to the console. ;;; </summary> main proc JsonSample.WriteSampleData(SAMPLE_FILE) JsonSample.ReadSampleData(SAMPLE_FILE) Console.ReadLine() endmain namespace JsonSample class JsonSample ;;; <summary> ;;; Method demonstrating using Utf8JsonWriter to output a JSON file ;;; </summary> public static method WriteSampleData, void filename, string endparams proc begin data jsonBuffer = new StringBuilder() data jsonWriter = Utf8JsonWriter.CreateUtf8JsonWriter(jsonBuffer) data writeChannel, i4 data iterator, i4 data stringData = "Hello World Hello World Hello World" jsonWriter.WriteStartObject() jsonWriter.WriteString(JSON_NAMEPROP, "MySampleObject") jsonWriter.WriteStartArray(JSON_SAMPLEARRAYPROP) for iterator from 1 thru 10 by 1 begin jsonWriter.WriteStartObject() jsonWriter.WriteNumber(JSON_IDPROP, iterator) jsonWriter.WriteBoolean(JSON_BOOLEANDATAPROP, GetRandomBool()) jsonWriter.WriteString(JSON_STRINGDATAPROP, stringData(iterator:11)) jsonWriter.WriteEndObject() end jsonWriter.WriteEndArray() jsonWriter.WriteEndObject() jsonWriter.Flush() jsonWriter.Reset() open(writeChannel = 0, O, filename) writes(writeChannel, jsonBuffer.ToString()) close writeChannel end endmethod ;;; <summary> ;;; Demonstrate the basic API for getting information out of a JsonDocument and JsonElements ;;; ;;; IMPORTANT NOTE: ;;; The JsonDocument object is the lifeblood of the rest of the objects. If it gets ;;; disposed or the scope ends, all the child JsonElement objects will also be ;;; disposed. If you need them to leave the scope intact, make sure you keep the ;;; JsonDocument object alive ;;; </summary> public static method ReadSampleData, void filename, string endparams proc begin data jsDoc, @JsonDocument data myElement, @JsonElement data elementName, @JsonElement data elementArray, @JsonElement data arrayLength, i4 data arrayIterator, i4 jsDoc = Parse(filename) myElement = jsDoc.RootElement elementName = myElement.GetProperty(JSON_NAMEPROP) elementArray = myElement.GetProperty(JSON_SAMPLEARRAYPROP) arrayLength = elementArray.GetArrayLength() for arrayIterator from 0 thru arrayLength-1 by 1 begin data itemId = elementArray[arrayIterator].GetProperty(JSON_IDPROP).GetInt32() data boolData = elementArray[arrayIterator].GetProperty(JSON_BOOLEANDATAPROP).GetBoolean() data stringData = elementArray[arrayIterator].GetProperty(JSON_STRINGDATAPROP).GetString() Console.WriteLine("Read in item " + %string(itemId) + " [" + %string(boolData) + ", " + stringData + "]") end end endmethod ;;; <summary> ;;; Get a "random" boolean. Just to add flavor to the sample data. ;;; </summary> ;;; <returns>true or false, pseudo-randomly</returns> private static method GetRandomBool, boolean endparams record number, int endrecord proc number = Utilities.GetRandomNumber() mreturn %rnd(number) > 16383 endmethod ;;; <summary> ;;; Utility method to read in a file from disk and return that file ;;; content parsed through JsonDocument.Parse ;;; </summary> ;;; <param name="filePath"></param> ;;; <returns></returns> public static method Parse, @JsonDocument req in filePath, string endparams record jsonFileContent, @StringBuilder firstBrace, int channel, int buffer, a1024 plays,string endrecord proc jsonFileContent = new StringBuilder() open(channel = 0, I, filePath) while (true) begin reads(channel, buffer, eof) if (firstBrace < 1) begin xcall instr(1, buffer, '{', firstBrace) if (firstBrace >= 1) buffer = buffer(firstBrace:1024-firstBrace) end jsonFileContent.Append(%atrim(buffer)) nextloop eof, jsonFileContent.Append(%atrim(buffer)) exitloop end close(channel) plays=jsonFileContent.ToString() mreturn JsonDocument.Parse(jsonFileContent.ToString()) endmethod endclass .region "Utilities" static class Utilities ;;; Stores the seed used by GetRandomNumber private static randomSeed, int, 1 ;;; <summary> ;;; This method is an alternative to Synergy randm(), which does not work ;;; well when hit with the same seeds in the same millisecond/second. This method ;;; tracks its own random seed and produces a random number based on seed and time. ;;; </summary> ;;; <returns></returns> public static method GetRandomNumber, int endparams record number, int ctime, int endrecord proc xcall time(ctime) xcall randm(randomSeed, randomSeed, ctime) xcall randm(number, randomSeed, ctime) mreturn number endmethod endclass .endregion endnamespace