Generating JSON & how to encapsulate a digit as a string

Primary tabs

Hi,

How do I generate JSON strings instead of integers, as follows:

{ "MyProperty":"1"}

all we seem to be able to generate is 

{ "MyProperty":1}

Its for an api that requires the former and as the former is valid JSON I'm surprised I am having so much trouble.

(Obviously I'm new, please be kind :D

Replies

I assume,  your JSON is generated by converting a dynamic object to string, i.e.: 

do obj.%ToJSON()

In elsecase, it's created manually an there you could put as many quotes as you like around the numbers.

For the first case, just make a function which converts the numbers into string, see below:

test ;test for stringify
   set a={},a.Name="John",a.Age=47,a.xx="ab:1234",a.City="Boston",a.Year=2020
   set a."Arr"=[11,22,"aa","bb"]
   set a."Obj"={"aa":"bb"}

   write a.%ToJSON(),!
   write $$stringify(a).%ToJSON(),!
   quit

stringify(x)
{
   set y=x.%GetIterator()
   while y.%GetNext(.i,.v) {
     set t=x.%GetTypeOf(i)
     if t="number" { d x.%Set(i,v,"string") } elseif t="array"!(t="object") { do stringify(v) }
   }
   quit x
}

The output  is then:

do ^test
{"Name":"John","Age":47,"xx":"ab:1234","City":"Boston","Year":2020,"Arr":[11,22,"aa","bb"],"Obj":{"aa":"bb"}}
{"Name":"John","Age":"47","xx":"ab:1234","City":"Boston","Year":"2020","Arr":["11","22","aa","bb"],"Obj":{"aa":"bb"}}


 

in IRIS if the data type is any numeric (%Integer, %Decimal, %Float, ..... or %Boolean)  the value is NOT enclosed in  Quotes.

Hi Robert, thanks - but you've merely defined the numeric data type we can do already:

{ "MyProperty":1}

What we are looking for is how to create the following non-numeric data type:

{ "MyProperty":"1"}

s dyn={}
d dyn.%Set("asNumber",123)
d dyn.%Set("asString",123,"string")


w dyn.%ToJSON()

{"asNumber":123,"asString":"123"}

Although the replies have already answered the question about creating JSON on Caché, I would look to add some discussion about additional features that support the %Library.DynamicArray and %Library.DynamicObject classes.  I am running my examples on IRIS Version 2020.2 (Build 199U) so a few of the features will not be available in older Caché versions.

You asked how does a programmer generate the following JSON:  { "MyProperty":"1"}.  If you are writing an ObjectScript program then just execute the statement:

SET x = { "MyProperty":"1"}

Whenever an ObjectScript expression contains language syntax which is enclosed either in nested curly brackets, { ... }, or in nested square brackets, [ ... ], then the ObjectScript compiler  will parse the contents of the bracketed expression using the rules for a JSON object or a JSON array respectively.  The strings and numbers and identifiers inside the bracketed syntax will be JSON literal values with one exception.  If a value inside the bracketed expression is enclosed in round parentheses, ( ... ) then the contents of the parenthesized value will have the syntax of an ObjectScript expression which will be evaluated at run time.

The %DynamicArray and %DynamicObject class objects can contain property values using JSON syntax for their representation as well as containing property values which are ObjectScript values.  Details of all the methods that can be applied to a %DynamicArray/%DynamicObject class object can be found in Class Reference web pages for the %Libraray.DynamicArray, %Library.DynamicObject and %Library.DynamicAbstractObject classes.

When you use the %ToJSON( ) method on a %DynamicArray/%DynamicObject then all the properties containing ObjectScript values will be translated to the appropriate JSON literal representation.  Certain ObjectScript values, such as an oref or $DOUBLE("NaN"), do not have a JSON representation and their occurrence will cause %ToJSON to generate an <ILLEGAL VALUE> signal.  When you use  the %Get(key) method to evaluate a property containing JSON representation then that JSON representation will first be converted into an ObjectScript value.  When you use the %Set(key,value) to modify a property then value is computed as a run-time ObjectScript expression and that ObjectScript computation becomes the value of the property.

The %Get(key,default,type) method call has two optional parameters.  The value of the default argument is returned (without any type conversions) if there is no property with the specified key argument.  If there is no default argument then an unassigned key argument will return the ObjectScript empty string.  The type argument contains a string that specifies what type conversion should be applied to the element with the specified key.  An empty string type argument or a missing type argument does the normal default conversion to ObjectScript.  The %Set(key,value,type) takes an optional type argument which is a string which specifies how the ObjectScript value argument is converted to a property element.  Th supported type arguments have changed over time so check the Class Reference web pages for documentation on what the possible type strings mean.

Consider:

USER>set x=["0.1230",12.30E-2,(.12300),("0.1230")]   ;; JSON string, JSON number, ObjScr number, ObjScr string              

USER>write x.%ToJSON()                                             
["0.1230",12.30E-2,0.123,"0.1230"]  ;; Everything converts to JSON representation (strings are the same)

USER>write x.%Get(0),",",x.%Get(1),",",x.%Get(2),",",x.%Get(3),","  ;; Everything converts to ObjectScript
0.1230,.123,.123,0.1230,

;; Newly added "json" type argument.
;; The 6-char string 0.1230 becomes 8 chars with leading/trailing double-quotes in JSON literal representation
;; The JSON number is not changed
;; The ObjectScript number picks up the leading zero required by JSON representation
USER>write x.%Get(0,,"json"),",",x.%Get(1,,"json"),",",x.%Get(2,,"json"),","
"0.1230",12.30E-2,0.123,
USER>set y=["null",null,""]    ;; JSON 4-char string null, JSON null value, JSON empty string                                    

USER>write y.%ToJSON( )   ;; JSON array printed as a %String                          
["null",null,""]
USER>write y.%Get(0),",",y.%Get(1),",",y.%Get(2),",",y.%Get(3),","   ;; Convert to ObjectScript 4 elements of 3-element array      
null,,,,  ;; Note that null, "" and unassigned all convert to empty string in ObjectScript
USER>write y.%Get(0,,"json"),",",y.%Get(1,,"json"),",",y.%Get(2,,"json"),",",y.%Get(3,,"json"),","  ;; Convert 4 elements to JSON
"null",null,"",,
;; Note: 4-char string null now is 6 chars with 2 "-chars, null identifier, empty string with only 2 "-chars,
;; and ObjectScript default null string for unassigned value (there is no legal JSON representation)

Unfortunately %Set does not yet support the "json" type argument but maybe that will happen in a future IRIS release.