JSON.Lua json.encode return nil - json

I'm new to LUA and tried learning coding this language with Garrys Mod.
I want to get the messages from the Garrys Mod chat and send them into a Discord channel with a webhook.
It works, but I tried expanding this project with embeded messages. I need JSON for this and used json.lua as a library.
But as soon as I send a message I retrieve the following error message:
attempt to index global 'json' (a nil value)
The code that causes the error is the following:
json.encode({ {
["embeds"] = {
["description"] = text,
["author"] = {
["name"] = ply:Nick()
},
},
} }),
The complete code:
AddCSLuaFile()
json = require("json")
webhookURL = "https://discordapp.com/api/webhooks/XXX"
local DiscordWebhook = DiscordWebhook or {}
hook.Add( "PlayerSay", "SendMsg", function( ply, text )
t_post = {
content = json.encode({ {
["embeds"] = {
["description"] = text,
["author"] = {
["name"] = ply:Nick()
},
},
} }),
username = "Log",
}
http.Post(webhookURL, t_post)
end )
I hope somebody can help me

Garry's Mod does provide two functions to work with json.
They are:
util.TableToJSON( table table, boolean prettyPrint=false )
and
util.JSONToTable( string json )
There is no need to import json and if I recall correctly it isn't even possible.
For what you want to do you need to build your arguments as a table like this:
local arguments = {
["key"] = "Some value",
["42"] = "Not always the answer",
["deeper"] = {
["my_age"] = 22,
["my_name"] = getMyName()
},
["even more"] = from_some_variable
and then call
local args_as_json = util.TableToJSON(arguments)
Now you can pass args_as_json to your
http.Post( string url, table parameters, function onSuccess=nil, function onFailure=nil, table headers={} )

Related

Having problem in making api calls in android studio using kotlin

I want to make api calls using json object request in android studio using kotlin.
This is the api.
How to access the 'name' in the array articles ?. I can access all the other things except 'id' and 'name'.
This is my code
val url = "https://news-api-don.herokuapp.com/api/v1?apiKey=20d14506791144cc8b424549c42068c0"
val jsonObjectRequest = JsonObjectRequest(
Request.Method.GET, url, null,
{
val newsJsonArray = it.getJSONArray("articles")
val newsArray = ArrayList<News>()
for(i in 0 until newsJsonArray.length()) {
val newsJsonObject = newsJsonArray.getJSONObject(i)
val news = News(
newsJsonObject.getString("title"),
newsJsonObject.getString("author"),
newsJsonObject.getString("url"),
newsJsonObject.getString("urlToImage")
)
newsArray.add(news)
}
mAdapter.updateNews(newsArray)
swipeRefreshLayout.isRefreshing = false
progressBar.visibility = View.GONE
},
{
Toast.makeText(this,"Something went wrong", Toast.LENGTH_LONG).show()
swipeRefreshLayout.isRefreshing = false
progressBar.visibility = View.GONE
}
)
MySingleton.getInstance(this).addToRequestQueue(jsonObjectRequest)
}

Parsing JSON error cannot read property 'url' of undefined

I have been trying to parse JSON, which have 3 different set of data where one element have various number of children and sometimes none. I am getting an error when there is no children present or only one present. I declared the JSON as var data.
JSON A
{
"floorplan": [
{
"title": "plan1",
"url": "https://media.plan1.pdf"
},
{
"title": "plan2",
"url": "https://media.plan2.pdf"
}
]
}
JSON B
{"floorplan": []}
JSON C
{
"floorplan": [
{
"title": "plan1",
"url": "https://media.plan1.pdf"
}
]
}
I parsed the JSON like this:
var items = JSON.parse(data);
return {
floorplan1: items.floorplan[0].url;
floorplan2: items.floorplan[1].url;
}
But, it only returned data for the JSON A, for other 2 it gave TypeError: Cannot read property 'url' of undefined.
I modified the code to check if floorplan have at least one child and then parse data.
var items = JSON.parse(data);
var plan = items.floorplan[0];
if(plan){
return {
floorplan1: items.floorplan[0].url;
floorplan2: items.floorplan[1].url;
}
}
The new code returned data for JSON A and B(as empty row), but gave error for C. C have one child still it got the error.
I also tried this code, still got the error for JSON C.
var items = JSON.parse(data);
var plan = items.floorplan[0];
var plan1;
var plan2;
if(plan){
plan1 = items.floorplan[0].url;
plan2 = items.floorplan[1].url;
}
return{
floorplan1 : plan1 ? plan1 : null;
floorplan2 : plan2 ? plan2 : null;
}
Is there any method I can try to get data returned for all 3 types of JSON?
let data = `
[{"floorplan": [{
"title": "plan1",
"url": "https://media.plan1.pdf"
}, {
"title": "plan2",
"url": "https://media.plan2.pdf"
}]},
{"floorplan": []},
{"floorplan": [{
"title": "plan1",
"url": "https://media.plan1.pdf"
}]}]`;
let json = JSON.parse(data);
//console.log(json);
json.forEach(items=>{
//console.log(items);
let o = {
floorplan1: items.floorplan.length > 0 ? items.floorplan[0].url : '',
floorplan2: items.floorplan.length > 1 ? items.floorplan[1].url : ''
};
console.log(o);
o = {
floorplan1: (items.floorplan[0] || {'url':''}).url,
floorplan2: (items.floorplan[1] || {'url':''}).url
};
console.log(o);
o = {
floorplan1: items.floorplan[0]?.url,
floorplan2: items.floorplan[1]?.url
};
console.log(o);
const {floorplan: [one = {url:''}, two = {url:''}]} = items;
o = {
floorplan1: one.url,
floorplan2: two.url
};
console.log(o);
});
Sure. A few ways, and more than I have here. I have put all the raw data into one string, parsed it into json and then iterated through that. In each loop my variable items will correspond to one of the json variables you created and referenced in your question as items.
In the first example, I check to make sure that items.floorplan has at least enough elements to contain the url I'm trying to reference, then use the ternary operator ? to output that URL if it exists or an empty string if it doesn't.
In the second example, I use the || (OR) operator to return the first object that evaluates to true. If items.floorplan[x] exists, then it will be that node, and if it doesn't I provide a default object with an empty url property on the right hand side, and then just use the url from the resulting object.
In the third, I use the optional chaining operator that was introduced in 2020. This method will return undefined if the url doesn't exist.
In the fourth example, I use destructuring to pull values out of the items variable, and make sure that there is a default value for url in case the items variable doesn't have a corresponding value.
But there are many more ways to go about it. These are just a few, and you can't necessarily say which approach is better. It's dependent on your intent and environment. With the exception of optional chaining (which shows undefined if the property doesn't exist), you can see these produce the same results.
DOCS for optional chaining: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining
DOCS for destructuring: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
An article on destructuring: https://javascript.info/destructuring-assignment

Cannot Create a Group, Invalid Scope

I am trying to create a group with the following dot.net code:
var groupDef = new Group()
{
DisplayName = name,
MailNickname = name + " " + GetTimestamp(),
Description = "Group/Team created for testing purposes",
Visibility = "Private",
GroupTypes = new string[] { "Unified" }, // same for all teams
MailEnabled = true, // same for all teams
SecurityEnabled = false, // same for all teams
AdditionalData = new Dictionary<string, object>()
{
["owners#odata.bind"] = owners.Select(o => $"{graphV1Endpoint}/users/{o.Id}").ToArray(),
["members#odata.bind"] = members.Select(o => $"{graphV1Endpoint}/users/{o.Id}").ToArray(),
}
};
// Create the modern group for the team
Group group = await graph.Groups.Request().AddAsync(groupDef);
I am getting a "Method not allowed." error thrown on the last line shown (Group group = await ...).
The scope parameter for the auth provider contains "Group.Read.All Group.ReadWrite.All".
If I add Group.Create to the scope I get an error stating the scope is invalid. Reducing the scope to just "Group.Create" also gives an error.
It certainly appears that I cannot create a group without Group.Create in the scope, but that throws an error at sign in.
Microsoft.Graph is version 3.19.0
Microsoft.Graph.Core is version 1.22.0
I ended up serializing the object and making the Http call with my own code. Basically, something like this:
string json = JsonConvert.SerializeObject(groupDef, jsonSettings);
Group group = HttpPost<Group>("/groups", json);
No permissions were changed.

Add new attribute to JSON

Using Node js and Sequelize ORM, i'm getting a data set. I need to add a new attribute to received data and send it to client side. This is what i tried.
Code Block 1
var varAddOns = { "id" : 5, "Name" : "Cheese"};
global.meal.findOne(
{
where: { id: 5 }
}).then(varMeal => {
var obj = {};
obj = varMeal;
obj.addons = varAddOns;
res.send(obj);
});
It returns a json like below. (Actually it does not contain "addons" data)
Code Block 2
{
"id": 12,
"mealName": "Burger",
"description": "Oily food",
}
but actually what i want is,
Code Block 3
{
"id": 12,
"mealName": "Burger",
"description": "Oily food",
"addons" : {
"id" : 5,
"Name" : "Cheese"
}
}
I tried something like below and it also wont work. (It returns same json as "Code Block 2'.)
Code Block 4
var newJson = {};
newJson = JSON.stringify(varMeal);
newJson['addons'] = varAddOns;
var retVal = JSON.parse(newJson);
res.send(retVal);
Can you help me to figure out, where the issue is?
EDIT
Code Block 5
var newJson = {};
newJson = varMeal;
newJson['addons'] = varAddOn;
var retVal = newJson;// JSON.parse(newJson);
res.send(retVal);
I tried 'Code block 5' as well. Same result comes out as 'Code block 2'. When I use JSON.parse(newJson), it was thrown an error. (Error is Unexpected token o in JSON at position 1)
You need to call .get on your model instance, and then attach extra properties to it:
var varAddOns = { "id" : 5, "Name" : "Cheese"};
global.meal.findOne(
{
where: { id: 5 }
}).then(varMeal => {
var obj = {};
obj = varMeal.get();
obj.addons = varAddOns;
res.send(obj);
});
A few things:
When you call findOne, Sequelize return a model instance, not a plain JS object with your data.
If you want to add extra properties to send to your user, you will first need to convert your model instance to a JS object with your data. You can do this by calling varMeal.get(). From there, you can add extra properties to it.
There is no need to prepend your variables with "var". It would be better to simply name your variable meal
you need the JSON to be an object when you are declaring newJson['addons'] as a nested object
Have you tried (in code block 4) not stringifying varMeal?

ServiceStack.Text.JsonObject.Parse vs. NewtonSoft.Json.Linq.JObject.Parse for nested tree of 'dynamic' instances?

I'd like to try ServiceStack's json parsing, but I've already figured out how to do something I need via Newtonsoft. Can this same thing by done via ServiceStack?
I've tried with the commented out code but it gives exceptions, see below for exception details.
Thanks!
Josh
[Test]
public void TranslateFromGitHubToCommitMessage()
{
const string json =
#"
{
'commits':
[
{
'author': {
'email': 'dev#null.org',
'name': 'The Null Developer'
},
'message': 'okay i give in'
},
{
'author': {
'email': 'author#github.com',
'name': 'Doc U. Mentation'
},
'message': 'Updating the docs, that\'s my job'
},
{
'author': {
'email': 'author#github.com',
'name': 'Doc U. Mentation'
},
'message': 'Oops, typos'
}
]
}
";
dynamic root = JObject.Parse(json);
//dynamic root = ServiceStack.Text.JsonSerializer.DeserializeFromString<JsonObject>(json);
//dynamic root = ServiceStack.Text.JsonObject.Parse(json);
var summaries = new List<string>();
foreach (var commit in root.commits)
{
var author = commit.author;
var message = commit.message;
summaries.Add(string.Format("{0} <{1}>: {2}", author.name, author.email, message));
}
const string expected1 = "The Null Developer <dev#null.org>: okay i give in";
const string expected2 = "Doc U. Mentation <author#github.com>: Updating the docs, that's my job";
const string expected3 = "Doc U. Mentation <author#github.com>: Oops, typos";
Assert.AreEqual(3, summaries.Count);
Assert.AreEqual(expected1, summaries[0]);
Assert.AreEqual(expected2, summaries[1]);
Assert.AreEqual(expected3, summaries[2]);
}
Exceptions Detail
When using the first commented out line:
dynamic root = ServiceStack.Text.JsonSerializer.DeserializeFromString<JsonObject>(json);
This exception occurs when the method is called.
NullReferenceException:
at ServiceStack.Text.Common.DeserializeListWithElements`2.ParseGenericList(String value, Type createListType, ParseStringDelegate parseFn)
at ServiceStack.Text.Common.DeserializeEnumerable`2.<>c__DisplayClass3.<GetParseFn>b__0(String value)
at ServiceStack.Text.Common.DeserializeSpecializedCollections`2.<>c__DisplayClass7. <GetGenericEnumerableParseFn>b__6(String x)
at ServiceStack.Text.Json.JsonReader`1.Parse(String value)
at ServiceStack.Text.JsonSerializer.DeserializeFromString[T](String value)
at GitHubCommitAttemptTranslator.Tests.GitHubCommitAttemptTranslatorTests.TranslateFromGitHubToCommitMessage()
And, the second:
dynamic root = ServiceStack.Text.JsonObject.Parse(json);
var summaries = new List<string>();
foreach (var commit in root.commits) // <-- Happens here
'ServiceStack.Text.JsonObject' does not contain a definition for 'commits'
Note: the message is 'string' does not contain a definition for 'commits' if I use code from line one, but change the type to or to instead of
at CallSite.Target(Closure , CallSite , Object )
at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0)
at GitHubCommitAttemptTranslator.Tests.GitHubCommitAttemptTranslatorTests.TranslateFromGitHubToCommitMessage()
After using DynamicJson from .NET 4.0 ServiceStack
Referring to mythz's comment:
This test case works, but if I modify it like below:
var dog = new { Name = "Spot", Parts = new { Part1 = "black", Part2 = "gray" }, Arr = new [] { "one", "two", "three"} };
var json = DynamicJson.Serialize(dog);
var deserialized = DynamicJson.Deserialize(json);
Then, deserialized.Name and Parts are fine, but Arr is of type string.
Also:
If I use ' quotes it doesn't appear to work. Is that normal? json2 works (to the degree that Arr is also still a string), but json3 does not work at all. It just returns
Immediate Window:
deserialized = DynamicJson.Deserialize(json3);
{}
base {System.Dynamic.DynamicObject}: {}
_hash: Count = 1
----- code: -----
var json2 =
#"
{
""Name"": ""Spot"",
""Parts"": {
""Part1"": ""black"",
""Part2"": ""gray""
},
""Arr"": [
""one"",
""two"",
""three""
]
}";
var json3 =
#"
{
'Name': 'Spot',
'Parts': {
'Part1': 'black',
'Part2': 'gray'
},
'Arr': [
'one',
'two',
'three'
]
}";
var deserialized = DynamicJson.Deserialize(json1);
ServiceStack's JSON Serializer also supports dynamic parsing, see examples of how to parse GitHub's JSON in the Dynamic JSON section of the wiki page.