-
-
Notifications
You must be signed in to change notification settings - Fork 218
Introduction JSON module #379
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
563b4dd to
c85d621
Compare
|
Do we really need One thing I like in Jansson library is that it has macros to check node's type along with letting users manually check the type using a functions like
looks cleaner in my opinion. Just implement them as macros or short functions, not as native calls. Also something that I never see people use, but is a really cool feature, is operator overloading for tags together with native function mapping. We could do that for although that eliminates to check if two handles ("references") are equal, but do we really need that in this context? By the way, it's lovely that you decided to also support AMXXInterface. Great job overall. 👍 |
I did this because Parson only allows compare values (which can be arrays, objects etc.). If it was one tag f.e After some thinking I believe that can be done but there's need to rewrite some class functions f.e. in int JSONMngr::ArrayGetArray(size_t array, size_t index)
{
JSON_Array *JSArray = json_array_get_array(m_Handles[array]->m_pArray, index);
return (JSArray) ? MakeHandle(JSArray, Handle_Array) : -1;
}if we change it to int JSONMngr::ArrayGetArray(size_t array, size_t index)
{
JSON_Array *JSArray = m_Handles[array]->m_pArray;
JSON_Array *JSChildArray = json_array_get_array(JSArray, index);
if (!JSChildArray)
{
return -1;
}
//Check is above
JSON_Value *JSValueChild = json_array_get_value(JSArray, index);
size_t handleid = MakeHandle(JSChildArray, Handle_Array);
SetHandleType(m_Handles[handleid], Handle_Value, reinterpret_cast<void *>(JSValueChild));
return handleid;
}we will be able to f.e. compare handles and with just one tag 😀. (because handles will have assigned value's pointer) About macros, I think they would be useful and convenient. About this:
I don't understand what do you mean, maybe it's the time (it's around 3:00am) but it'd be great if you could explain me it in other words or more detailed. |
|
Awesome stuff |
6547166 to
1cd76a3
Compare
|
Update. Removed:
For 1st there's no replacement because they aren't needed anymore. Changed:
Added:
Examples has been updated. |
|
About the library licence, I think you need to add an entry here: https://github.com/alliedmodders/amxmodx/blob/master/public/licenses/ACKNOWLEDGEMENTS.txt. Not a requirement, but I would not mind having a full pawn testsuite plugin. |
|
Awesome |
|
@Ni3znajomy are you alive? |
|
@Arkshine Of course I am 😃 but I've been a little busy recently. |
|
It's not like I don't want. It just happened that Ni3znajomy did a PR related to JSON. About the library used, I don't know exactly what are the difference between Parson and Jansson. Looks like both are more or less the same. Here some benchmark. Parson seems easier though, and the dot notation is quite handy. |
|
@Arkshine but we have jansson wrapper for sourcemod too, so i thought it would be better to use same library. I can make code more better ( it will be nice if this module will be useful ) |
|
Some offtop: For example: Or: |
|
@WPMGPRoSToTeMa Nice idea it looks more like SourcePawn syntax but I've got little problem with it, when there is 1 define it's ok, compiler starts complain when 2 or more defines appear then I got Plugin src #include <amxmodx>
#include <json>
#define JSON::%0.IsObject() (%0 != Invalid_JSON && json_get_type(%0) == JSONObject)
#define JSON::%0.IsArray() (%0 != Invalid_JSON && json_get_type(%0) == JSONArray)
#define JSON::%0.IsNum() (%0 != Invalid_JSON && json_get_type(%0) == JSONNumber)
public plugin_init() { } |
|
@Ni3znajomy Maybe something like this stock foo(JSON:handle, const method[])
{
// process it
}
#define JSON::%1.%2(); foo(%1, #%2)
public plugin_init()
{
JSON::handle.IsObject()
}
/* or just declare enum */
enum MethodT {
IsObject,
IsString
};
stock foo(JSON:handle, MethodT:method)
{
// process it
}
#define JSON::%1.%2(); foo(%1, %2)
public plugin_init()
{
JSON::handle.IsObject()
} |
|
@Ni3znajomy But with this it works: So, you can use this: |
|
Reviewing takes time, especially when no one is willing to review. ¯\_(°╭╮°)_/¯ |
|
ok hope it wont take long. |
|
Fix memory leaks and increase max nesting
Order of items in an array is preserved after removing an item.
|
If possible, can you provide a VS project? |
|
I don't use nor have VS 😕 |
|
It's okay, I will PR your branch later. By the way, did you test your module after all these late changes? |
|
Yeah, there was a mistake when I started using |
Add VS projects files and fix mixed tab/spaces
modules/json/JsonNatives.cpp
Outdated
| auto value = MF_GetAmxAddr(amx, params[1]); | ||
| if (!JsonMngr->IsValidHandle(*value)) | ||
| { | ||
| MF_LogError(amx, AMX_ERR_NATIVE, "Invalid JSON value! %d", *value); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure erroring on json_free is useful. I believe others APIs don't do that as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gonna be removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done along with comments.
| #pragma loadlib json | ||
| #endif | ||
|
|
||
| enum JSONType |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing comment.
plugins/include/json.inc
Outdated
| JSONBoolean = 6 | ||
| }; | ||
|
|
||
| enum JSON |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing comment.
|
It looks like in a good & sane place now. The code is quite straightforward. If someone wants to say something about this module, let's hear now, before merging happens. |
plugins/include/json.inc
Outdated
| /* | ||
| * Overloaded operators for convenient comparing | ||
| */ | ||
| native bool:operator==(const JSON:value1, const JSON:value2) = json_equals; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know I initially suggested this, but after putting more thought into it, I'd actually get rid of it.
While it's a cool feature, no other handle types in AMXX override operator==. People are used to operator== comparing handles/references, not their data, so an implicit deep comparison of JSON objects may be a bad idea.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree as well, deep comparison should be explicit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
modules/json/JsonMngr.h
Outdated
| virtual ~JSONMngr(); | ||
|
|
||
| // Handles | ||
| virtual bool IsValidHandle(JS_Handle id, JSONHandleType type = Handle_Value); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should use override here and with any other overridden method instead of virtual. So instead of
virtual bool IsValidHandle(JS_Handle id, JSONHandleType type = Handle_Value);it should be
bool IsValidHandle(JS_Handle id, JSONHandleType type = Handle_Value) override;Here virtual indicates that given method may be overridden further by a derived class. override ensures that the overridden method exists in the base class (IJSONMngr) and is of the same type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
|
Alright. Let's do it! |

Features
objectA.objectB.value)How does it work?
Decoding
Sample JSON data was taken from GitHub API. We want to get information about last 2 commits (authors' names, their ids, committers' names and some extra).
Sample output
File contains info about 30 commits COMMIT b9997eb628f975d72a8e1d5d556a4b4c0d1b6aec Author name: IgnacioFDM Author id: 12388603 Is author site admin: NO Committer name: Vincent Herbet Committer id: 360640 Is committer site admin: NO ///////////////////////// COMMIT a53e7905db37f8e1b63929bdb27f8e5d0b10b1be Author name: KliPPy Author id: 9073673 Is author site admin: NO Committer name: Vincent Herbet Committer id: 360640 Is committer site admin: NOEncoding
Sample output in file
{ "utf-8 string": "ęąćłóþπąœßćźżðæŋə©ś", "https": "https:\/\/alliedmods.net", "comment": "\/**\/", "text": "\"text\"", "number": { "int": 45, "float": { "easy": 31.700001, "hard": -0.001320 } }, "null": null, "bool": { "true": true, "false": false }, "\/\/": null, "x^2 array": [ 0, 1, 4, 9, 16 ] }Output in the console
Iteration
We can iterate arrays and objects.
Arrays
Objects
API Overview
json_parseparses JSON string or file that contains it.json_equalschecks equality of 2 values.json_validatevalidates value.json_get_parentgets value's parent.json_get_typegets value type.json_init_{type}creates handle with specific type.json_get_{type}gets specific data from handle.json_deep_copycopies value.json_freefrees handle.Array API
json_array_get_{type}gets data from array.json_array_get_countgets count of elements in array.json_array_replace_{type}replaces value in array. (removes the old one if any)json_array_append_{type}appends value in array.json_array_removeremoves value from specific index.json_array_clearclears array.Object API (supports dot notation)
json_object_get_{type}gets data from object.json_object_get_countgets count of keys in object.json_object_get_namegets name of object's key.json_object_get_value_atgets value from object.json_object_has_valuechecks if object has value and type.json_object_set_{type}sets value in object. (removes the old one if any)json_object_removeremoves value in object.json_object_clearclears object.Serialization API
json_serial_sizegets size of serialization.json_serial_to_stringcopies serialized string to buffer.json_serial_to_filecopies serialized string to file.Feel free to test it, give your thoughts and suggestions about code, documentation, API etc.