Skip to main content

For a test I am working on at the moment, I am using the DEX library to automatically generate an AIMMS library for a webservice based on the OpenAPI json spec.

 

Unfortunately,  in one of the models I have a property with the following definition:

"value": {
"anyOf": :
{
"type": "number"
},
{
"type": "string"
}
],
"title": "Value"
}

 

I am not responsible for the webservice, so did not know that something was changed (the anyOf). It took me a long time to figure out why after the api call was done there was no data anymore. I did not get any errors or warnings and I unfortunately forgot to check the CallErrorCode parameter.

 

Finally, I was able to find what went wrong by modifying the generated callback procedure and replace the line

CallErrorCode := dex::ProtectedReadFromFile(ResponseFile('responsebody'), responsefileMapping('responsebody')) ;

with a block/onerror do piece where I manually call the dex::ReadFromFile procedure allowing me to catch the error. In my case, the error finally made it clear to me what went wrong: Could not convert “somestringvalue” to numerical value.

 

Instead of having a ProtectedReadFromFile that catches all errors and reduces them to a binary state error/no-error it might be interesting to have a list of the messages of all errors/warnings that were caught in the process allowing a developer to pinpoint a bit quicker what went wrong.

 

Furthermore, wondering if you have a potential solution for dealing with these multi-type values in DEX. I am pretty sure the best solution might be telling the people creating the webservice not to mix types…  😉 But the standard does allow for it, so in theory I could run into this more often. For now I have solved it by modifying the generated code for this webservice to read everything into a string parameter and try to convert each string into a numerical value and have another binary parameter indicating whether a numerical value was found (i.e. whether the VAL function did not raise an error)

Hi@gdiepen 

Certainly there is a fix for that. You can annotate the value schema with an x-aimms-type-switch extension. That should take care of two identifiers being created and two entries in the mapping. 

As an example I've added a part of the Google BigQuery openapi spec.

      "JsonObject": {
"additionalProperties": {
"$ref": "#/components/schemas/JsonValue"
},
"description": "Represents a single JSON object.",
"type": "object"
},
"JsonValue": {
"x-aimms-type-switch" : true,
"anyOf" : :
{
"type" : "number"
},
{
"type" : "string"
},
{
"type" : "boolean"
}
]
}

With the type-switch annotation, these two fragments lead to the following identifiers being created:

with the following mapping:

<?xml version="1.0"?>
<AimmsJSONMapping iterative-reset="ogbq::i_childInstance,dex::schema::childNode,dex::schema::extbinding">
<ExternalBinding binds-to="ogbq::i_instance" binding="ogbq::CurrentInstance" />
<ObjectMapping>
<ValueMapping name-binds-to="ogbq::i_JsonValue_patterns" name-regex=".*" maps-to="ogbq::_JsonObject::JsonObject_number(ogbq::i_instance,ogbq::i_JsonValue_patterns)" type-switch="1" />
<ValueMapping name-binds-to="ogbq::i_JsonValue_patterns" name-regex=".*" maps-to="ogbq::_JsonObject::JsonObject_string(ogbq::i_instance,ogbq::i_JsonValue_patterns)" type-switch="1" />
<ValueMapping name-binds-to="ogbq::i_JsonValue_patterns" name-regex=".*" maps-to="ogbq::_JsonObject::JsonObject_boolean(ogbq::i_instance,ogbq::i_JsonValue_patterns)" number-type="boolean" type-switch="1" />
</ObjectMapping>
</AimmsJSONMapping>

Although a number of the annotations have been documented, all available annotations aren't described extensively, as it all would become pretty technical, and the number of use cases not too big

And I can already hear you say, can't the code figure this out all by itself, and potentially it could (in fact the current refactor of the generator would stand a much better chance), but it doesn't have an extremely high priority, as it is fairly easy to patch in the x-aimms-… annotations into any update of an openapi spec for which you have to regenerate a client.


Reply


Didn't find what you were looking for? Try searching on our documentation pages:

AIMMS Developer & PRO | AIMMS How-To | AIMMS SC Navigator