Check if value exists in Lua table - json

I am running Lua on ESP8266 Wifi module with NodeMCU firmware. My application is listening on TCP port for JSON requests. When I get the request I parse it using:
jsonRequest = json.decode(request)
So then I can access desired value with:
jsonRequest.object.state
Everything works perfectly until I send an invalid JSON (without "object"). When that happens I get this error: Lua API (attempt to index a nil value) and my program stops with execution.
MY PROBLEM: I would like to check if my table contains that key before accessing, but I can't find a way to do it.
I could do it with pairs function and loop through all keys and check if there is the right one, but that would require lots of code because I have multiple nested objects in my JSON.
Any ideas?

To check if the table jsonRequest contains the key "object", use:
if jsonRequest.object ~= nil then
If the values stored in the table won't be the boolean value false, you can also use:
if jsonRequest.object then

Related

Processing a Kafka message using KSQL that has a field that can be either an ARRAY or a STRUCT

I'm consuming a Kafka topic published by another team (so I have very limited influence over the message format). The message has a field that holds an ARRAY of STRUCTS (an array of objects), but if the array has only one value then it just holds that STRUCT (no array, just an object). I'm trying to transform the message using Confluent KSQL. Unfortunately, I cannot figure out how to do this.
For example:
{ "field": {...} } <-- STRUCT (single element)
{ "field": [ {...}, {...} ] } <-- ARRAY (multiple elements)
{ "field": [ {...}, {...}, {...} ] <-- ARRAY (multiple elements)
If I configure the field in my message schema as a STRUCT then all messages with multiple values error. If I configure the field in my message schema as an ARRAY then all messages with a single value error. I could create two streams and merge them, but then my error log will be polluted with irrelevant errors.
I've tried capturing this field as a STRING/VARCHAR which is fine and I can split the messages into two streams. If I do this, then I can parse the single value messages and extract the data I need, but I cannot figure out how to parse the multivalue messages. None of the KSQL JSON functions seem to allow parsing of JSON Arrays out of JSON Strings. I can use EXTRACTJSONFIELD() to extract a particular element of the array, but not all of the elements.
Am I missing something? Is there any way to handle this reasonably?
In my experience, this is one use-case where KSQL just doesn't work. You would need to use Kafka Streams or a plain consumer to deserialize the event as a generic JSON type, then check object.get("field").isArray() or isObject(), and handle accordingly.
Even if you used a UDF in KSQL, the STREAM definition would be required to know ahead of time if you have field ARRAY<?> or field STRUCT<...>
I finally solved this in a roundabout way...
First, I created an initial stream reading the transaction as a stream of bytes using KAFKA format instead of JSON format. This allows me to put a filter conditional filter on the data so I can fork the stream into a version for the single (STRUCT) variation and a version for the multiple (ARRAY) variation.
The initial stream looks like:
CREATE OR REPLACE STREAM `my-topic-stream` (
id STRING KEY,
data BYTES
)
WITH (
KAFKA_TOPIC='my-topic',
VALUE_FORMAT='KAFKA'
);
Forking that stream looks like this with a second for a multiple version filtering for IS NOT NULL:
CREATE OR REPLACE STREAM `my-single-stream`
WITH (
kafka_topic='my-single-topic'
) AS
SELECT *
FROM `my-topic-stream`
WHERE JSON_ARRAY_LENGTH(EXTRACTJSONFIELD(FROM_BYTES(data, 'utf8'), '$.field')) IS NULL;
At this point I can create a schema for both variations, explode field, and merge the two streams back together. I don't know if this can be refined to be more efficient, but this successfully processes the transactions as I wanted.

Oracle ords: How to create put/post method with collection

I created a post method to receive the geolocation data of customers:
Post method
When I call the post method with the JSON:
{"customer": 1, "latitude":-21.13179, "longitude":-47.736782 }
my PL/SQL Script works.
Now I'd like to send a group of records but I don't know how to do it.
I created a PUT method to receive a collections of geolocations and I constructed a script just to parse the parameter:
Put method
When I call the put method with the JSON:
{
"items":[
{
"customer":1,
"latitude":-21.13179,
"longitude":-47.736782
},
{
"customer":1,
"latitude":-21.13179,
"longitude":-47.736782
}
]
}
PL/SQL code:
declare
l_values apex_json.t_values;
begin
apex_json.parse (
p_values => l_values,
p_source => :items );
end;
I received the message:
400 - Bad Request - Expected a value but got: START_ARRAY.
What I'm doing of wrong?
I want to create a post/put method to receive a collection.
Thanks for your help.
There is an example in OracleBase that shows a way to use 'JSON_Table' in 12c and 'JSON_Obect_t' pl/sql in 12Cr2. The JSON data is passed as a blob to the stored proc which then parses and updates/whatever. I have not tested it yet but it looks like a good approach to deal with collections which apparently cannot be handled by ORDS "out of the box". I had experimented with using the bulkload approach to load a temp table but it was for csv only and a bit tedious. Here's Jeff Smiths blog post on that
I have not tested this yet, I rebuilt my approach to send each entry individually but eventually I'll need to use this. I'll update this answer when I do with examples.
I am facing the same issue and the reason would be what is posted in the below URL.
https://community.oracle.com/thread/2182167?start=0&tstart=0
"In APEX Listener 1.1 the PL/SQL Hander will automatically convert JSON properties to implicit parameters. Note this will only work for simple JSON objects, arrays or nested object are not supported."
Basically - one can't pass collections/arrays. I'm not sure if this has changed now or if there are any plans to change this in the roadmap.

Handling errors with Ember Data using the JSON API standard [duplicate]

I am using Ember 1.13.7 and Ember Data 1.13.8, which by default use the JSON-API standard to format the payloads sent to and received from the API.
I would like to use Ember Data's built-in error handling in order to display red "error" form fields to the user. I have formatted my API error responses as per the JSON-API standard, e.g.
{"errors":[
{
"title":"The included.1.attributes.street name field is required.",
"code":"API_ERR",
"status":"400",
}
]}
and when I attempt to save my model the error callback is being correctly executed. If I look within the Ember Inspector I can see that the model's "isError" value is set to true but I can't see how Ember Data is supposed to know which field within the model is the one in an error state? I see from the official JSON-API pages (http://jsonapi.org/format/#errors) that you can include a "source" object within the error response:
source: an object containing references to the source of the error,
optionally including any of the following members:
pointer: a JSON Pointer [RFC6901] to the associated entity in the request document
[e.g. "/data" for a primary data object, or "/data/attributes/title"
for a specific attribute].
parameter: a string indicating which query
parameter caused the error.
but is this what I should be doing in order to tell Ember Data which fields it should mark as being in an error state?
If anyone can help shed some light on this I'd be grateful.
Thanks.
Note the answer below is based on the following versions:
DEBUG: -------------------------------
ember.debug.js:5442DEBUG: Ember : 1.13.8
ember.debug.js:5442DEBUG: Ember Data : 1.13.9
ember.debug.js:5442DEBUG: jQuery : 1.11.3
DEBUG: -------------------------------
The error handling documentation is unfortunately scattered around at the moment as the way you handle errors for the different adapters (Active, REST, JSON) are all a bit different.
In your case you want to handle validation errors for your form which probably means validation errors. The format for errors as specified by the JSON API can be found here: http://jsonapi.org/format/#error-objects
You'll notice that the API only specifies that errors are returned in a top level array keyed by errors and all other error attributes are optional. So seemingly all that JSON API requires is the following:
{
"errors": [
{}
]
}
Of course that won't really do anything so for errors to work out of the box with Ember Data and the JSONAPIAdapter you will need to include at a minimum the detail attribute and the source/pointer attribute. The detail attribute is what gets set as the error message and the source/pointer attribute lets Ember Data figure out which attribute in the model is causing the problem. So a valid JSON API error object as required by Ember Data (if you're using the JSONAPI which is now the default) is something like this:
{
"errors": [
{
"detail": "The attribute `is-admin` is required",
"source": {
"pointer": "data/attributes/is-admin"
}
}
]
}
Note that detail is not plural (a common mistake for me) and that the value for source/pointer should not include a leading forward slash and the attribute name should be dasherized.
Finally, you must return your validation error using the HTTP Code 422 which means "Unprocessable Entity". If you do not return a 422 code then by default Ember Data will return an AdapterError and will not set the error messages on the model's errors hash. This bit me for a while because I was using the HTTP Code 400 (Bad Request) to return validation errors to the client.
The way ember data differentiates the two types of errors is that a validation error returns an InvalidError object (http://emberjs.com/api/data/classes/DS.InvalidError.html). This will cause the errors hash on the model to be set but will not set the isError flag to true (not sure why this is the case but it is documented here: http://emberjs.com/api/data/classes/DS.Model.html#property_isError). By default an HTTP error code other than 422 will result in an AdapterError being returned and the isError flag set to true. In both cases, the promise's reject handler will be called.
model.save().then(function(){
// yay! it worked
}, function(){
// it failed for some reason possibly a Bad Request (400)
// possibly a validation error (422)
}
By default if the HTTP code returned is a 422 and you have the correct JSON API error format then you can access the error messages by accessing the model's errors hash where the hash keys are your attribute names. The hash is keyed on the attribute name in the camelcase format.
For example, in our above json-api error example, if there is an error on is-admin your would access that error like this:
model.get('errors.isAdmin');
This will return an array containing error objects where the format is like this:
[
{
"attribute": "isAdmin",
"message": "The attribute `is-admin` is required"
}
]
Essentially detail is mapped to message and source/pointer is mapped to attribute. An array is returned in case you have multiple validation errors on a single attribute (JSON API allows you to return multiple validation errors rather than returning just the first validation to fail). You can use the error values directly in a template like this:
{{#each model.errors.isAdmin as |error|}}
<div class="error">
{{error.message}}
</div>
{{/each}}
If there are no errors then the above won't display anything so it works nicely for doing form validation messages.
If you API does not use the HTTP 422 code for validation errors (e.g., if it uses 400) then you can change the default behavior of the JSONAPIAdapter by overriding the handleResponse method in your custom adapter. Here is an example that returns a new InvalidError object for any HTTP response status code that is 400.
import DS from "ember-data";
import Ember from "ember";
export default DS.JSONAPIAdapter.extend({
handleResponse: function(status, headers, payload){
if(status === 400 && payload.errors){
return new DS.InvalidError(payload.errors);
}
return this._super(...arguments);
}
});
In the above example I'm checking to see if the HTTP status is 400 and making sure an errors property exists. If it does, then I create a new DS.InvalidError and return that. This will result in the same behavior as the default behavior that expects a 422 HTTP status code (i.e., your JSON API error will be processed and the message put into the errors hash on the model).

Good Practice? Eval function from JSON sent over WebSockets

I am considering the following architecture. A client connected to a server via websockets send a JSON package to the server. Inside of the JSON besides other data there is "action":"somefunction();". The server will then parse the JSON and if the action is not empty then it will eval and thus run that command.
The alternative to this would be to simply put a string "somefunction" in the action attribute and have a switch statement on the server to run the appropriate code.
Thoughts or other possibilities?
What you describe does not prevent a hostile client from sending arbitrary code to be executed. It is a security hole.
If you want to have client code trigger some functions on the server, then pass some data that your server will parse and check to make sure that only the appropriate code is executed. It could be a JSON structure like this that the client sends:
{
"name": "foo",
"arguments": ["a", "b", "c"]
}
When the server receives it and parses it with JSON.parse, it verifies that name is a valid value and invokes the corresponding function. The functions could be in a structure like this
var dispatch = {
foo: function (a, b, c) { },
bar: function (a) { }
// etc...
}
And once the JSON data is parsed and stored into a variable named data (for instance), the invocation could be:
dispatch[data.name].apply(undefined, data.arguments)
If needed return data could also be returned to the client as a JSON structure.
I tend to use window["function_name_as_string"](param1,param2); if I am calling a function by name with dynamic data.

Neo4j creating multiple nodes using multiple params json

I am new to neo4j and still figuring out why this is failing.
Here is my json query that I am passing
FOREACH(p in {props} |
MERGE (n:Router {NodeId:p.NodeId})-[r:has_interface]->(I:Interface {IfIPAddress:p.IfIPAddress})
ON CREATE SET I = p
ON MATCH SET I = p)
props is a array of collection that I am passing in params.
Props has a property NodeId.
This is what I want to achieve
1) I have already created thousands nodes labelled Router with property NodeId
2) I want to create Interfaces for these nodes.
3) Now if the NodeId in the props collection matches the Router NodeId, I want to create Interface with relation to the Router node as -> (has_interface)
When I run this json query using curl and json it gives me exception saying
"message" : "Query not prepared correctly!",
"exception" : "InternalException"
What can be the issue. I checked the query many times and it seems to be correct
You are probably using version 2.0.0 which had a bug. Use 2.0.1 (or above) and you're fine, as your syntax is correct.