Welcome to the SRP Forum! Please refer to the SRP Forum FAQ post if you have any questions regarding how the forum works.

JSON

Hi
In the srp utility's i see an xml tool. Maybe a good idea to also create a json tool.
We have an App wich communicates with json. It's hard to decode json sometimes.

Ed

Comments

  • Ed,

    Have you seen the RTI_JSON function that is already built into OpenInsight 9? I've used it a few times for interacting with web services and it works well once you get the hang of it. Here is an example I wrote to remind me of how to serialize (i.e. turn an object into a string) and then de-serialize ( turn a string back into an object)

    * * Make 3 separate JSON objects * menuObj1 = RTI_JSON('', 'New', 'OBJECT') Call RTI_JSON(menuObj1, 'SetObject', 'name', 'Menu w/ Delims Action 1') Call RTI_JSON(menuObj1, 'SetObject', 'link', '/your/function/action1') Call RTI_JSON(menuObj1, 'SetObject', 'pos', '1') menuObj2 = RTI_JSON('', 'New', 'OBJECT') Call RTI_JSON(menuObj2, 'SetObject', 'name', 'Menu Action 2') Call RTI_JSON(menuObj2, 'SetObject', 'link', '/your/function/action2') Call RTI_JSON(menuObj2, 'SetObject', 'pos', '2') menuObj3 = RTI_JSON('', 'New', 'OBJECT') Call RTI_JSON(menuObj3, 'SetObject', 'name', 'Menu Action 3') Call RTI_JSON(menuObj3, 'SetObject', 'link', '/your/function/action3') Call RTI_JSON(menuObj3, 'SetObject', 'pos', '3') * * Place each JSON object into a parent object * to show embedding * menuItems = RTI_JSON('', 'New', 'ARRAY') call Rti_JSON(menuItems, 'SetObject', '[0]', menuObj1) call Rti_JSON(menuItems, 'SetObject', '[1]', menuObj2) call Rti_JSON(menuItems, 'SetObject', '[2]', menuObj3) *Turn the JSON object into a string for sharing menuItemsJSON = RTI_JSON(menuItems, 'Stringify') *Reverse the process *Turn the string back into an object RetObjs = RTI_JSON(menuItemsJSON, "Parse") *get the second embedded object (index starts at 0) menuObj1reverse = RTI_JSON(RetObjs, 'GetObject', '[1]') *Get the original values of each property menuObj1name = RTI_JSON(menuObj1reverse, 'GetValue', 'name') menuObj1link = RTI_JSON(menuObj1reverse, 'GetValue', 'link') menuObj1pos = RTI_JSON(menuObj1reverse, 'GetValue', 'pos')
  • Ed,

    Your point is well taken, especially for people who still use older versions of OI. Otherwise, Jared's suggestion to use RTI_JSON is probably the best option. Our support for XPath is built upon the Microsoft library. If there us a similar library that supports JSON then there is a possibility that we will add this to our toolkit.
  • Hi,

    Thank you for your reply.

    And yes i have tried rti_json but have you tried to set a value to 0?
    This function get's confused with '0'.
    Call RTI_JSON(menuObj2, 'SetObject', 'pos', '0')
    The zero does not get returned

    And in json there is a difference in an empty string ("") and an empty nummeric (null) this diffence is not possible with RTI_SON.

    Ed
  • Hmmm,

    I did some renewed testing...
    My problem was with decoding Json.
    For decoding purpose RTI_JSON can work for me.

    Thank you for the tip.

    Ed
  • Ed,

    I thought I would come back to this thread and point out, in case you hadn't already received the news, that we have released our own JSON library now.
  • Where can I find this JSON library?
  • Ed,

    It is included in SRP Utilities, the same library that includes SRP Extract XML. In case you aren't subscribing to our blog here is the article.
  • I (finaly) read the documentation but did not find anything on making a difference between a numeric null and an empty string.

    {"Number":null}
    {"String":""}

    Also how to set a boolean.
  • Ed,

    Ordinarily you would not need to make a null. Null in JSON is not the same as an empty string, which is different than how BASIC+ sees things. Therefore, we do not have a way for you to create a null value. If you have a business case for this please let us know so we can evaluate this further.

    Use the SETVALUE method with a value of 1 or 0 and then specify type as "BOOLEAN" so that it does not think you are setting the value of a number.
  • SRP_JSON(IntegerHandle, "NEW", "NUMBER", "")
    should make a numeric null?
    Or am I wrong?

    I will do some testing with this utility.
    It looks good!
  • Ed,

    I think you are confused. Numbers and Null are both types of JSON values. There is no such thing as a "numeric null". Are you trying to create a specific JSON object or are you just playing around? If you are trying to create a specific object then post the object here and we can help you with the syntax.
  • We run an ipad app with OI data. And when a number-field is not assigned I have to give null back to the app.
    The datacollector in IOS is configured with strings, numbers and booleans.

    example:
    I don't now your age!
    { "Guys": [ { "Name": "Ed", "Age": 54 }, { "Name": "Don", "Age": null } ] }
  • Ed,

    I see. So if you omitted "Age" altogether from an object would the iPad app not handle that properly?

    If not, then I understand your need to set a null value. The phrase "numerical null" was confusing to me. "Age" is merely a name (or Key). The value is either number or null, in this case.

    Let me take this back to the team and look at what we can do.
  • Ed,

    Okay, we have updated the SRP_JSON library to support the creation of null values. All services that allow you to specify a value type will now allow you to specify NULL. For instance:
    SRP_JSON(GuyObj, "SETVALUE", "Age", "", "NULL")
    This will be released in a short while. We are still testing an update to another SRP Utilities feature. If you want to play with a pre-release version then email me privately and I will send you something.
  • SRP_JSON(ObjectHandle, "SETVALUE", "Age", "", "NUMBER")
    If "SETVALUE" is called for the type "NUMBER" and the value is an empty string then the json value should be null and not zero.
    This is simple logic, or is this not compatible for your use
  • Ed,

    I suppose we could make that work on a technical level. That is, it is not impossible. However, I would argue that this is not a good design. This would basically be asking the API to make a specific implicit rule for this combination: NewValue = "", Type = "NUMBER".

    In general, the Type argument is the final arbiter. In the above case you are suggesting the opposite to occur. Someone else might easily argue that this should always result in a zero rather than null. In my opinion, if null is the required value then it is better to be explicit so that there are no misunderstandings with the code's intent. Consider the following examples:

    SRP_JSON(ObjectHandle, "SETVALUE", "Age", "", "BOOLEAN")
    SRP_JSON(ObjectHandle, "SETVALUE", "Age", "Red", "BOOLEAN")
    SRP_JSON(ObjectHandle, "SETVALUE", "Age", "White", "NUMBER")
    SRP_JSON(ObjectHandle, "SETVALUE", "Age", "Blue", "NULL")
    In all of the above examples the NewValue argument is contrary to the Type argument. So, do we assume the NewValue argument is correct or that the Type is correct? In all of these cases SRP_JSON assumes that Type is correct and it attempts to create a value based on that assumption. In your specific example you want the opposite to occur.

    I always like the idea of an API being smart and forgiving. This is why the above examples I provided do not return an error (which is arguably a valid approach, but these will resolve a value based on the Type.) But I dislike inconsistency or behavior that is based on a rather specific use case.

    That's how I look at this but I could be misguided. I'm open to being persuaded otherwise.
  • Ah, its getting clear to me now, and I can follow your approach.
    So we have code a little more to catch then empty numbers.

    In the examples i see that srp_json calls sometimes as a function and sometimes as a subroutine.
    I declared srp_json both as function and subroutine and that works. Is that correct?

    Ed
  • Ed,

    SRP_JSON can always be called as a subroutine if you do not care to check for a status response. In my case I typically declare it as both a function and subroutine. Many of my calls are subroutines (for simplicity) since I it is unlikely that it will fail. I call it as a function when it really matters, like when I am using the "NEW" method.
  • Ed (and others who are using SRP_JSON),

    Kevin and I had a productive discussion about this. Your desire to store a null value automatically without having to write additional logic is well appreciated. It speaks to the reason we love the MV environment so much. Everything is flexible and we can be very efficient. The challenge for us when we marry the MV environment to something else based on different rules (e.g., a more rigid typed environment) is finding reasonable middle ground.

    So we are intending to make a change to the SRP _JSON API that will help you and at the same time it will maintain the core design of the API in which the Type argument still dictates how the NewValue argument will be interpreted.

    This change, however, will potentially break existing programs that are already using SRP_JSON. Ordinarily we would not do this but since we believe that adoption of SRP_JSON is probably limited by this time, we are hoping this will have very little - or no - impact on existing routines.

    Our API will still behave the same when the Type argument is explicitly set. That guiding principle still makes sense to us. What we will do is alter the behavior when no Type argument is set, what we refer to as auto or default behavior. At present, the API assumes that String is implied when the Type argument is absent. Now, we will make it so it will work like this:
    • An empty string will be treated as a null type.
    • A number will be treated as a number type.
    • Anything else will be treated as a string type.

    This deviates from the current behavior in which every value is assumed to be a string type unless specified differently in the Type argument. Herein lies where potential implementations of SRP_JSON might break.

    Ed, for you this means you can simplify your code to look like this:
    SRP_JSON(ObjectHandle, "SETVALUE", "Age", AgeVar)
    Where AgeVar is your variable storing the numerical age or an empty string. SRP_JSON will treat this as a number or null type as appropriate.

    Note that boolean types must still be explicitly specified. We did not think it was safe to assume that 1 or 0 is a boolean. However, when specifying a boolean type, a NewValue of 0 or "" will be treated as false and anything else by be treated as true. This imitates the way BASIC+ handles boolean operations.

    Any objections to these changes? Sound off now or forever hold your peace...
  • Bravo!

    One more question
    SRP_JSON(ObjectHandle, "SETVALUE", "Age", AgeVar)
    is the same as
    SRP_JSON(ObjectHandle, "SETVALUE", "Age", AgeVar,"")
  • Ed,

    Yes. Those would behave the same.
  • ADDVALUE with no result

    script below returns unexpected "[ ]"
    If SRP_JSON(ArrayHandle, "NEW", "ARRAY") then SRP_JSON(ArrayHandle, "ADDVALUE", "12345") SRP_JSON(ArrayHandle, "ADDVALUE", 67890, "NUMBER") SRP_JSON(ArrayHandle, "ADDVALUE", 1, "BOOLEAN") JSON = SRP_JSON(ArrayHandle, "STRINGIFY", "FAST") SRP_JSON(ArrayHandle, "RELEASE") end return JSON
  • Hi Ed,

    Good catch. We confirmed the bug and believe we have it fixed. A new build of SRP Utilities has been forwarded to me for testing. If this works for me I'll email you the latest pre-release build for your own use and testing.
Sign In or Register to comment.