String passed to JSON library turns into a table - json

When I execute this code (Windows 10) i get an error from within the library.
local json = loadfile("json.lua")()
local handle = io.popen("curl \"https://someurl.com\"")
local result = handle:read("*all")
handle:close()
local output = json:decode(result)
The error in the console:
lua: json.lua:377: expected argument of type string, got table
stack traceback:
[C]: in function 'error'
json.lua:377: in method 'decode'
monitor.lua:10: in main chunk
[C]: in ?
I'm running the code on Windows 10 with a console and using this library: https://github.com/rxi/json.lua
This function always returns the same error, even if I try different types of arguments, i.e. numbers or strings.
function json.decode(str)
if type(str) ~= "string" then
error("expected argument of type string, got " .. type(str))
end
local res, idx = parse(str, next_char(str, 1, space_chars, true))
idx = next_char(str, idx, space_chars, true)
if idx <= #str then
decode_error(str, idx, "trailing garbage")
end
return res
end

local output = json:decode(result)
is syntactic sugar for
local output = json.decode(json, result)
json is a table.
Hence inside function json.decode the following if statement is entered:
if type(str) ~= "string" then
error("expected argument of type string, got " .. type(str))
end
which produces the observed error.
To fix this you can either change the function definiton to
function json:decode(str)
-- code
end
Or you call
local output = json.decode(result)
You should pick the second one as changing the json library will affect code that already uses json.decode as intended by the author.

Related

How to pass an object as argument to an anonymous function in MATLAB?

I'm working on a MATLAB app that programatically creates anonymous functions to evaluate any native MATLAB function and pass it a list of variables as argument. In the example below, 'formula' contains a string with the function and arguments to be evaluated (e.g., "sum( var1, var2 )" ). The formulas sometimes contain function calls nested within function calls, so the code below would be used recursively until obtaining the final result:
Func2 = str2func( sprintf( '#(%s) %s', strjoin( varNames, ',' ), formula ) );
This evaluates fine for native MATLAB functions. But there's a particular case of a function (named Func1) I made myself that not only needs the list of variables but also an object as argument, like this:
function output = Func1( anObject, varNames )
% do some stuff with the object and the vars
end
For this particular function, I've tried doing this:
Func2 = str2func( sprintf( '#(%s,%s) %s', "objectToPassToFunc1", strjoin( varNames, ',' ), "Func1(objectToPass,""" + strjoin( varNames, '","' ) +""")" ) )
...which doesn't throw an error, but Func1 doesn't receive the objectToPassToFunc1, instead it gets values from one of the variables in varNames. And I don't know why.
So how can I correctly pass the object to Func1????
Matlab doesn't care about the type of arguments you pass to a function. As a matter of fact, the input could be scalar, vector, matrix, and even an object of a class. See the following example.
classdef ClassA
methods
function print(~)
disp('method print() is called.');
end
end
end
This class has only one method. Now, let us define an anonymous function func which accepts one input.
func = #(arg) arg.print;
Notice that we explicitly assume that the input is an object of ClassA. If you pass another type of data to this function, Matlab will throw an error. To test the code,
obj = ClassA;
func = #(arg) arg.print;
func(obj)
To avoid the error, you may need to check the type of the input before using it. For example,
function [] = func(arg)
% check if arg is an object of ClassA
if isa(arg,'ClassA')
arg.print;
end
end
Now you can pass different types for the input without getting an error.

Save decoded JSON values in Lua Variables

Following script describes the decoding of a JSON Object, that is received via MQTT. In this case, we shall take following JSON Object as an example:
{"00-06-77-2f-37-94":{"publish_topic":"/stations/test","sample_rate":5000}}
After being received and decoded in the handleOnReceive function, the local function saveTable is called up with the decoded object which looks like:
["00-06-77-2f-37-94"] = {
publish_topic = "/stations/test",
sample_rate = 5000
}
The goal of the saveTable function is to go through the table above and assign the values "/stations/test" and 5000 respectively to the variables pubtop and rate. When I however print each of both variables, nil is returned in both cases.
How can I extract the values of this table and save them in mentioned variables?
If i can only save the values "publish_topic = "/stations/test"" and "sample_rate = 5000" at first, would I need to parse these to get the values above and save them, or is there another way?
local pubtop
local rate
local function saveTable(t)
local conversionTable = {}
for k,v in pairs(t) do
if type(v) == "table" then
conversionTable [k] = string.format("%q: {", k)
printTable(v)
print("}")
else
print(string.format("%q:", k) .. v .. ",")
end
end
pubtop = conversionTable[0]
rate = conversionTable[1]
end
local lua_value
local function handleOnReceive(topic, data, _, _)
print("handleOnReceive: topic '" .. topic .. "' message '" .. data .. "'")
print(data)
lua_value = JSON:decode(data)
saveTable(lua_value)
print(pubtop)
print(rate)
end
client:register('OnReceive', handleOnReceive)
previous question to thread: Decode and Parse JSON to Lua
The function I gave you was to recursively print table contents. It was not ment to be modified to get some specific values.
Your modifications do not make any sense. Why would you store that string in conversionTable[k]? You obviously have no idea what you're doing here. No offense but you should learn some basics befor you continue.
I gave you that function so you can print whatever is the result of your json decode.
If you know you get what you expect there is no point in recursively iterating through that table.
Just do it like that
for k,v in pairs(lua_value) do
print(k)
print(v.publish_topic)
print(v.sample_rate)
end
Now read the Lua reference manual and do some beginners tutorials please.
You're wasting a lot of time and resources if you're trying to implement things like that if you do not know how to access the elements of a table. This is like the most basic and important operation in Lua.

Decode and Parse JSON to Lua

I have following JSON data I would like to decode to Lua to access each the publish_topic and sample_rate value.
{"00-06-77-2f-37-94":{"publish_topic":"/stations/test","sample_rate":5000}}
If I understand correctly the Lua table will look like this:
{00-06-77-2f-37-94 = "publish_topic":"/stations/test","sample_rate":5000}
Next I would go through the table to save each value into a local variable.
However, if I try printing out the values of the table (using following code), I get 'nil' as return. Is the code for reading table values wrong?
Does the table have two values or is it just the one: ["publish_topic":"/stations/test","sample_rate":5000] ?
lua_value = JSON:decode(data)
for _,d in pairs(lua_value) do
print(lua_value[d])
end
local topic = lua_value[0]
local timer = lua_value[1]
end
Edit: I am using following JSON library for Lua: http://regex.info/blog/lua/json
Edit2: #Piglet: I implemented your script and modified it by adding a table (conversionTable) in which both elements "publish_topic":"/stations/test" and "sample_rate:5000" would be respectively saved in the variables pubtop and rate. When I however print each of both variables, nil ist returned in both cases.
How can I extract the information out of this table to save in variables?
Ultimately I actually only would like to save the values "/stations/test" and "5000" into these variables. Would I need to parse each of the elements above to get these or is there another way?
local pubtop
local rate
local function printTable(t)
local conversionTable = {}
for k,v in pairs(t) do
if type(v) == "table" then
conversionTable [k] = string.format("%q: {", k)
printTable(v)
print("}")
else
print(string.format("%q:", k) .. v .. ",")
end
end
pubtop = conversionTable[0]
rate = conversionTable[1]
end
local lua_value
local function handleOnReceive(topic, data, _, _)
print("handleOnReceive: topic '" .. topic .. "' message '" .. data .. "'")
-- This sample publishes the received messages to test/topic2
print(data)
lua_value = JSON:decode(data)
printTable(lua_value)
print(pubtop)
print(rate)
end
client:register('OnReceive', handleOnReceive)
I don't know which json library you're using so I can't tell you wether JSON:decode(data) is the correct way.
Assuming lua_value would like like so:
local lua_value = {
["00-06-77-2f-37-94"] = {
publish_topic = "/stations/test",
sample_rate = 5000
}
}
Then your loop
for _,d in pairs(lua_value) do
print(lua_value[d])
end
will indeed print nil.
lua_value has a single element at key "00-06-77-2f-37-94" which is a table.
Each loop iteration will give you a key value pair. So d is actually the value and hence the inner table of lua_value
So you're actually doing this:
local innerTable = lua_value["00-06-77-2f-37-94"]
print(lua_value[innerTable])
Of course lua_value[innerTable] is nil.
Edit:
Try something like
function printTable(t)
for k,v in pairs(t) do
if type(v) == "table" then
print(string.format("%q: {", k))
printTable(v)
print("}")
else
print(string.format("%q:", k) .. v .. ",")
end
end
end
printTable(lua_value)

understanding how a lua function does work?

I have a HTML project that uses mutiple lua scripts , I have big issue unterstanding the functionality of one function ( I'm new to lua) :
........................
all the requires have been done and the paths are also defined
local fs = require "lfs"
local const = {}
for num = 1, 14 do
const[num] = assert(
dofile (const_path .. mkfilename(num)),
"Failed to load constant configuration ".. num ..".")
end
local function file_number() --this is the function that causes me a headach
local ci, co, num = ipairs(const)-- when I print num is 0 and ci,co are nil
local vi, vo, _ = fs.dir(virt_path)-- what does _ mean here ?
local function vix(o)
local file = vi(o)
if file == nil then return nil end
local number = file:match("^(%d+).lua$")
if number == nil then return vix(o) end
return tonumber(number)
end
local function iter(o, num)
return ci(o.co, num) or vix(o.vo, num)---where is ci defined or impplemented
end
return iter, {co=co, vo=vo}, num-- what 's the return value here ?
end
the function works but I still don't understand why and how, I 'll be greatfull for any hint.
_ is conventionally a throw-away variable.
In this case though it serves no purpose and could just as easily be left out entirely.
ci should be a function and co should be a table there.
Similarly (though I can't say for sure about vo) for vi and vo.
That function is constructing its own iterator using the iterator functions and state returns from the ipairs and fs.dir functions.
The line return iter, {co=co, vo=vo}, num is returning an interator function, a table for state, and the initial loop variable (0 from the initial ipairs call).
When used in a loop that will loop over the values from ci and vix.

argument name in the lua function call

I am looking for a more pleasant way to add an argument name while calling a function.
Something which is better than either of these
local ret = foo( --[[argNam1 =]] true)
local ret = foo( true ) -- first argument is argName1
I tried
local ret = foo( argNam1 = true)
but I got error
')' expected near '='
You could use named parameters, if that's what you want. Lua tables are good for imitating that behavior. So instead of passing all parameters separated by a comma, you pass a single table object; that has named keys.
If that is your foo() function:
local foo(parameters)
print(parameters.argNam1)
end
Then you could call it like: local ret = foo{argNam1 = true}
Or call it like this:
local arguments = {
argNam1 = true,
argNam2 = "foobar"
}
local ret = foo(arguments)