apama

How to parse value from HTTP JSON response payload


I’m relatively new to Apama. I’m using v10.3.1. I’m following the following snippet to do a REST request within a monitor:

http://www.apamacommunity.com/documents/10.3.1.1/apama_10.3.1.1_webhelp/apama-webhelp/#page/apama-webhelp%2Fco-ConApaAppToExtCom_httpclient_using_predefined_generic_event_definitions.html%23wwconnect_header

The action to handle the response currently looks as follows:


action handleResponse(Response response){
        if response.isSuccess(){
            print "###The response payload is :" + response.payload.toString();
        }

        else {
            print "###Request failed. Response status is: " + response.statusCode.toString() + " | " + response.statusMessage;
        }
    }

I’m looking for the best way to extract the value of the following property within the JSON response payload:

assetparents.references[0].managedObject.name (here “SOME”).

I tried different ways but always ran into an error.

The print statement provides the following output for the response payload:



###The response payload is :com.apama.util.AnyExtractor(any(string,"

{"owner":"some@one.com","additionParents":{
    "self":"https://somebaseurl/inventory/managedObjects/5706999/additionParents","references":[]
},
"childDevices":{
    "self":"https://somebaseurl/inventory/managedObjects/5706999/childDevices","references":[]
},

"childAssets":{
    "self":"https://somebaseurl/inventory/managedObjects/5706999/childAssets","references":[]
},
"creationTime":"2019-05-09T11:36:10.197Z",
"lastUpdated":"2019-05-10T05:28:07.893Z",
"childAdditions":{
    "self":"https://somebaseurl/inventory/managedObjects/5706999/childAdditions",
    "references":[{
        "managedObject":{"name":"Escalate alarmtest",
        "self":"https://somebaseurl/inventory/managedObjects/5706698",
        "id":"5706698"},
        "self":"https://somebaseurl/inventory/managedObjects/5706999/childAdditions/5706698"
    }
]},
"name":"SOME Test Device",
"deviceParents":{
    "self":"https://somebaseurl/inventory/managedObjects/5706999/deviceParents",
    "references":[]
},
"assetParents":{
    "self":"https://somebaseurl/inventory/managedObjects/5706999/assetParents",
    "references":[{
        "managedObject":{
            "additionParents":{
                "self":"https://somebaseurl/inventory/managedObjects/5706682/additionParents",
                "references":[]
            },
            "childDevices":{
                "self":"https://somebaseurl/inventory/managedObjects/5706682/childDevices",
                "references":[]
            },
            "childAssets":{
                "self":"https://somebaseurl/inventory/managedObjects/5706682/childAssets",
                "references":[]
            },
            "childAdditions":{
                "self":"https://somebaseurl/inventory/managedObjects/5706682/childAdditions",
                "references":[]
            },
            "name":"SOME",
            "deviceParents":{
                "self":"https://somebaseurl/inventory/managedObjects/5706682/deviceParents",
                "references":[]
            },
            "assetParents":{
                "self":"https://somebaseurl/inventory/managedObjects/5706682/assetParents",
                "references":[]
            },
            "self":"https://somebaseurl/inventory/managedObjects/5706682",
            "id":"5706682"
        },
        "self":"https://somebaseurl/inventory/managedObjects/5706999/assetParents/5706682"
    }]
},
"self":"https://somebaseurl/inventory/managedObjects/5706999",
"id":"5706999",
"c8y_ActiveAlarmsStatus":{
    "minor":0,
    "critical":1
},
"c8y_IsDevice":{},
"ax_Customer":"SOME CUSTOMER",
"c8y_SupportedMeasurements":["c8y_Temperature"]}"))

Besides parsing the individual property, what is the recommended way to map the entire object to an Apama event?

If you could provide a code snippet it would be greatly appreciated.

Many thanks Mathias


Solution

  • To address your second question, namely "what is the recommended way to map the entire object to an Apama event?":

    I've defined several events which will map to the JSON you provided:

    event Reference {
        string self;
        any managedObject;
    }
    
    event Object {
        string self;
        sequence<Reference> references;
    }
    
    event ActiveAlarmsStatus {
        integer minor;
        integer critical;
    }
    event IsDevice {}
    
    event ManagedObject {
        string owner;
        string self;
        string id;
        string name;
        string creationTime;
        string lastUpdated;
        Object additionParents;
        Object childDevices;
        Object childAssets;
        Object childAdditions;
        Object deviceParents;
        Object assetParents;
        ActiveAlarmsStatus c8y_ActiveAlarmsStatus;
        IsDevice c8y_IsDevice;
        string ax_Customer;
        sequence<string> c8y_SupportedMeasurements;
    }
    

    Because a ManagedObject contains an Object, which contains a Reference which itself contains a ManagedObject, the EPL wouldn't compile due to the recursive types. Therefore, in Reference we use an any type to mask the ManagedObject. this allows the EPL to compile.

    However, because an any hides the type, we don't know what type to convert it to, and so instead we have an any containing a dictionary. This is fine though, because we can use some helper functions to extract the information we want:

    action GetSequenceReference(sequence<any> s) returns sequence<Reference> {
        sequence<Reference> ret := new sequence<Reference>;
        any r := new any;
        for r in s {
            ret.append(<Reference>r);
        }
        return ret;
    }
    action GetSequenceString(sequence<any> s) returns sequence<string> {
        sequence<string> ret := new sequence<string>;
        any r := new any;
        for r in s {
            ret.append(<string>r);
        }
        return ret;
    }
    
    action GetObject(any a) returns Object {
        log "Getting object from: " + a.toString() at INFO;
        dictionary<any,any> dict := <dictionary<any,any> >a;
    
        Object ret := new Object;
    
        ret.self := <string>dict.getDefault( "self", "" );
        ret.references := GetSequenceReference( <sequence<any> >dict.getDefault( "references", new sequence<any> ) );
    
        return ret;
    }
    
    action GetActiveAlarmsStatus(any a) returns ActiveAlarmsStatus {
        log "Getting active alarms status from: " + a.toString() at INFO;
        dictionary<any,any> dict := <dictionary<any,any> >a;
    
        ActiveAlarmsStatus ret := new ActiveAlarmsStatus;
    
        ret.minor := <integer>dict.getDefault( "minor", 0 );
        ret.critical := <integer>dict.getDefault( "critical", 0 );
    
        return ret;
    }
    action GetIsDevice(any a) returns IsDevice {
        log "Getting is device from: " + a.toString() at INFO;
        dictionary<any,any> dict := <dictionary<any,any> >a;
    
        IsDevice ret := new IsDevice;
    
        return ret;
    }
    action GetManagedObject(any a) returns ManagedObject {
    
        log "Getting managed object from: " + a.toString() at INFO;
        dictionary<any,any> dict := <dictionary<any,any> >a;
    
        ManagedObject ret := new ManagedObject;
        ret.owner := <string>dict.getDefault( "owner", "" );
        ret.self := <string>dict.getDefault( "self", "" );
        ret.id := <string>dict.getDefault( "id", "" );
        ret.name := <string>dict.getDefault( "name", "" );
        ret.creationTime := <string>dict.getDefault( "creationTime", "" );
        ret.lastUpdated := <string>dict.getDefault( "lastUpdated", "" );
        ret.additionParents := GetObject( dict.getDefault( "additionParents", new dictionary<any,any> ) );
        ret.childDevices := GetObject( dict.getDefault( "childDevices", new dictionary<any,any> ) );
        ret.childAssets := GetObject( dict.getDefault( "childAssets", new dictionary<any,any> ) );
        ret.childAdditions := GetObject( dict.getDefault( "childAdditions", new dictionary<any,any> ) );
        ret.deviceParents := GetObject( dict.getDefault( "deviceParents", new dictionary<any,any> ) );
        ret.assetParents := GetObject( dict.getDefault( "assetParents", new dictionary<any,any> ) );
        ret.c8y_ActiveAlarmsStatus := GetActiveAlarmsStatus( dict.getDefault( "c8y_ActiveAlarmsStatus", new dictionary<any,any> ) );
        ret.c8y_IsDevice := GetIsDevice( dict.getDefault( "c8y_IsDevice", new dictionary<any,any> ) );
        ret.ax_Customer := <string>dict.getDefault( "ax_Customer", "" );
        ret.c8y_SupportedMeasurements := GetSequenceString( <sequence<any> >dict.getDefault( "c8y_SupportedMeasurements", new sequence<any> ) );
        return ret;
    }
    
    

    Using these helper functions, we can extract the information from our original event:

    action handleResponse(Response response){
        if response.isSuccess(){
            ManagedObject mo := GetManagedObject( response.payload.toDictionary() );
            log "###The response payload is :" + mo.toString() at INFO;
        }
    
        else {
            log "###Request failed. Response status is: " + response.statusCode.toString() + " | " + response.statusMessage at INFO;
        }
    }
    

    And there you have it! A fully mapped event.