How to capture error message from third-party-library in Lua? - json

I have adopted the LuaJSON to parse JSON. The parse call seems like that:
-- file.lua
local res = json.decode.decode(json_str)
if res == nil then
throw('invalid JSON')
end
...
But if the json_str is badly formated, the decode() will stop within LuaJSON and interrupt the execution of file.lua. I want the control flow to return to my function instead, so I can provide a custom error notification.
I have browsed the LuaJSON APIs, and there is no callback-like error handling. I want to know is there any Lua mechanism that allows me to handle errors occuring within LuaJSON from within file.lua?

The problem here is that the decode function calls error if it encounters an error.
This is Lua's equivalent to an exception handling mechanism. What you want to do is call the decode function in protected mode:
local success, res = pcall(json.decode.decode, json_str);
if success then
-- res contains a valid json object
...
else
-- res contains the error message
...
end

In your example, if you are using CJSON version 2.1.0, there is a new "cjson.safe" module, which will return nil and error msg if any exception occurred in encode or decode procedure.
local decoder = require("cjson.safe").decode
local decoded_data, err = decoder(data)
if err then
ngx.log(ngx.ERR, "Invalid request payload:", data)
ngx.exit(400)
end

Related

JSON functions in SQLite

I am trying to get the SQLite JSON functions to work with Go and the github.com/mattn/go-sqlite3 driver but not having much luck.
Using VSCode as my editor I did:
go get github.com/mattn/go-sqlite3
go build --tags "json1" github.com/mattn/go-sqlite3
Wrote my test app which calls the following function
func IsJSONValid(payloadID int) bool {
var isValid int
sql := `select json_valid(json_payload) from exec_payload where payload_id = ?`
err = database.QueryRow(sql, payloadID).Scan(&isValid)
if err != nil {
log.Println(err)
log.Println("Fatal - unable to validate JSON payload")
LogDb("IsJSONValid", "unable to validate JSON payload")
return false
}
if isValid == 0 {
return false
}
return true
}
Executing the code/func I get the following error:
no such function: json_valid
I know I can write a Struct and handle the logic to validate the json data stored in the sqlite table column - however it's pretty convenient to use / have the function already available in the DB - running the same query in the sqlite command line tool executes without any issues.

How we can read a JSON file with Go Programming Language?

I'm working on a translation project on my Angular app. I already create all the different keys for that. I try now to use Go Programming Language to add some functionalities in my translation, to work quickly after.
I try to code a function in Go Programming Language in order to read an input user on the command line. I need to read this input file in order to know if there is missing key inside. This input user must be a JSON file. I have a problem with this function, is blocked at functions.Check(err), in order to debug my function I displayed the different variable with fmt.Printf(variable to display).
I call this function readInput() in my main function.
The readInput() function is the following :
// this function is used to read the user's input on the command line
func readInput() string {
// we create a reader
reader := bufio.NewReader(os.Stdin)
// we read the user's input
answer, err := reader.ReadString('\n')
// we check if any errors have occured while reading
functions.Check(err)
// we trim the "\n" from the answer to only keep the string input by the user
answer = strings.Trim(answer, "\n")
return answer
}
In my main function I call readInput() for a specific command I created. This command line is usefull to update a JSON file and add a missing key automatically.
My func main is :
func main() {
if os.Args[1] == "update-json-from-json" {
fmt.Printf("please enter the name of the json file that will be used to
update the json file:")
jsonFile := readInput()
fmt.Printf("please enter the ISO code of the locale for which you want to update the json file: ")
// we read the user's input
locale := readInput()
// we launch the script
scripts.AddMissingKeysToJsonFromJson(jsonFile, locale)
}
I can give you the command line I use for this code go run mis-t.go update-json-from-json
Do you what I'm missing in my code please ?
Presuming that the file contains dynamic and unknown keys and values, and you cannot model them in your application. Then you can do something like:
func main() {
if os.Args[1] == "update-json-from-json" {
...
jsonFile := readInput()
var jsonKeys interface{}
err := json.Unmarshal(jsonFile, &jsonKeys)
functions.Check(err)
...
}
}
to load the contents into the empty interface, and then use the go reflection library (https://golang.org/pkg/reflect/) to iterate over the fields, find their names and values and update them according to your needs.
The alternative is to Unmarshal into a map[string]string, but that won't cope very well with nested JSON, whereas this might (but I haven't tested it).

How to determine the error type from MySQL

I'm really confused how to get the error type from a failed query line with the MySQL import. There is no real documentation on it, so it has me real confused.
I have:
result, err := db.Exec("INSERT INTO users (username,password,email) VALUES (?,?,?)", username, hashedPassword, email)
if err != nil {
// handle different types of errors here
return
}
I could print err but its just a string, not liking the idea of peeking at strings to know what went wrong, is there no feedback to get an error code to perform a switch on or something along those lines? How do you do it?
Indeed, checking the content of the error string is a bad practice, the string value might vary depending on the driver verison. It’s much better and robust to compare error numbers to identify what a specific error is.
There are the error codes for the mysql driver, the package is maintained separately from the main driver package. The mechanism to do this varies between drivers, however, because this isn’t part of database/sql itself. With that package you can check the type of error MySQLError:
if driverErr, ok := err.(*mysql.MySQLError); ok {
if driverErr.Number == mysqlerr.ER_ACCESS_DENIED_ERROR {
// Handle the permission-denied error
}
}
There are also error variables.
Ref
normally in packages you could see Variables if the package author want to separate errors make variable for each of them like :
https://golang.org/pkg/database/sql/#pkg-variables
you could see errors and you could switch the error in return and case each error variable.
example:
result, err := db.Exec("INSERT INTO users (username,password,email) VALUES (?,?,?)", username, hashedPassword, email)
if err == sql.ErrNoRows {
// handle error
return
}
if err == sql.ErrTxDone {
// handle error
return
}

LUA load JSON configuration from file

I'm trying to move old LUA method which was loading some JSON content from file into global variable into "class". But I get following errors all the time:
attempt to call field 'decode' (a nil value)
attempt to index global 'cjson' (a nil value)
I don't know lua well but i tried almost all combinations without result so can you explain why this errors occurs?
Current implementation of module looks like:
Config = {}
Config.__index = Config
function Config.create(config_filename)
local cjson = require("cjson")
local config = {}
setmetatable(config,Config)
local f = io.open(config_filename, "r")
local content = f:read("*a")
f:close()
config = cjson.decode(content)
return config
end
return Config
As final result I want to execute something like this from other file:
local config_class = require("config")
local config = config_class.create("/path/to/file.json")
ngx.say(config:some_configuration_data())
As the error message tells you cjson and decode are nil values which cannot be indexed or called.
require will load some file and run the contained code and pass the return value through. If you run a Lua script it behaves like a function which returns nil by default. So unless you specify what the script returns require will return nil.
I don't know what is inside your cjson file that you require but it obviously does not return the wanted json implementation but nil.
So the code in cjson should return a Lua table with a function stored under key "decode".

Using BubbleWrap to read JSON files

I have a backend to an IOS application. I am trying to read the data from my rails backend by using JSON. My bubbleWrap get request is as follows.
BW::HTTP.get("url_here/children/1.json") do |response|
json = BW::JSON.parse response.body.to_str
for line in json
p line[:name]
end
end
It doesn't bring any data back, it actually breaks my code. I can't find any documentation with an example of how to use REST from rubymotion/Bubblewrap and pull data back to my application.
Any help is appreciated.
Here's a handy class abstraction that I use in a lot of my applications... it completely abstracts the API call logic from the view controller logic for separation of concerns and is heavily modeled after Matt Green's Inspect 2013 talk.
class MyAPI
APIURL = "http://your.api.com/whatever.json?date="
def self.dataForDate(date, &block)
BW::HTTP.get(APIURL + date) do |response|
json = nil
error = nil
if response.ok?
json = BW::JSON.parse(response.body.to_str)
else
error = response.error_message
end
block.call json, error
end
end
end
Then to call this class we do:
MyAPI.dataForDate(dateString) do |json, error|
if error.nil?
if json.count > 0
json.each do |cd|
# Whatever with the data
end
else
App.alert("No Results.")
end
else
App.alert("There was an error downloading data from the server. Please check your internet connection or try again later.")
end
end
Always check the response code before parsing the response body. You might
BW::HTTP.get(url) do |response|
if response.ok?
data = BW::JSON.parse(response.body.to_str)
# make sure you have an array or hash before you try iterating over it
data.each {|item| p item}
else
warn "Trouble"
end
end
Also make sure you sanity-check the JSON response vs your code's expectation. Perhaps the JSON is an array and not a hash?