Veteran Member
|
05-11-2012
, 12:28
Re: [EXTENSION] SMJansson 2.3.1/1 (2012-05-07)
|
#3
|
Converting JSON to KeyValues
This is a lossy conversion as KeyValues don't support arrays as JSON does and therefore this example sets the index of the value as the key in the resulting KeyValues structure.
CODE
PHP Code:
#pragma semicolon 1
#include <sourcemod>
#include <smjansson>
new Handle:g_hKV;
public OnPluginStart() {
// Build a JSON string without breaking the forums layout
new String:sJSON[4096] = "{ \"id\": \"0001\", \"type\": \"donut\", \"name\": \"Cake\", \"ppu\": 0.55,";
StrCat(sJSON, sizeof(sJSON), "\"batters\": { \"batter\": [ { \"id\": \"1001\", \"type\": \"Regular\" },");
StrCat(sJSON, sizeof(sJSON), "{ \"id\": \"1002\", \"type\": \"Chocolate\" }, { \"id\": \"1003\", \"type\": \"Blueberry\" },");
StrCat(sJSON, sizeof(sJSON), "{ \"id\": \"1004\", \"type\": \"Devil's Food\" } ] },");
StrCat(sJSON, sizeof(sJSON), "\"topping\": [ { \"id\": \"5001\", \"type\": \"None\" }, { \"id\": \"5002\", \"type\": \"Glazed\" },");
StrCat(sJSON, sizeof(sJSON), "{ \"id\": \"5005\", \"type\": \"Sugar\" }, { \"id\": \"5007\", \"type\": \"Powdered Sugar\" },");
StrCat(sJSON, sizeof(sJSON), "{ \"id\": \"5006\", \"type\": \"Chocolate with Sprinkles\" }, { \"id\": \"5003\", ");
StrCat(sJSON, sizeof(sJSON), "\"type\": \"Chocolate\" }, { \"id\": \"5004\", \"type\": \"Maple\" } ]}");
// Create a new JSON object
new Handle:hObj = json_load(sJSON);
g_hKV = CreateKeyValues("root");
ProcessElement("root", hObj);
KeyValuesToFile(g_hKV, "json-kv.out");
CloseHandle(g_hKV);
CloseHandle(hObj);
}
public ProcessElement(String:sKey[], Handle:hObj) {
switch(json_typeof(hObj)) {
case JSON_OBJECT: {
// It's another object
KvJumpToKey(g_hKV, sKey, true);
IterateJsonObject(Handle:hObj);
KvGoBack(g_hKV);
}
case JSON_ARRAY: {
// It's another array
KvJumpToKey(g_hKV, sKey, true);
IterateJsonArray(Handle:hObj);
KvGoBack(g_hKV);
}
case JSON_STRING: {
new String:sString[1024];
json_string_value(hObj, sString, sizeof(sString));
KvSetString(g_hKV, sKey, sString);
}
case JSON_INTEGER: {
KvSetNum(g_hKV, sKey, json_integer_value(hObj));
}
case JSON_REAL: {
KvSetFloat(g_hKV, sKey, json_real_value(hObj));
}
case JSON_TRUE: {
KvSetNum(g_hKV, sKey, 1);
}
case JSON_FALSE: {
KvSetNum(g_hKV, sKey, 0);
}
case JSON_NULL: {
KvSetString(g_hKV, sKey, "");
}
}
}
public IterateJsonArray(Handle:hArray) {
for(new iElement = 0; iElement < json_array_size(hArray); iElement++) {
new Handle:hValue = json_array_get(hArray, iElement);
new String:sElement[4];
IntToString(iElement, sElement, sizeof(sElement));
ProcessElement(sElement, hValue);
CloseHandle(hValue);
}
}
public IterateJsonObject(Handle:hObj) {
new Handle:hIterator = json_object_iter(hObj);
while(hIterator != INVALID_HANDLE) {
new String:sKey[128];
json_object_iter_key(hIterator, sKey, sizeof(sKey));
new Handle:hValue = json_object_iter_value(hIterator);
ProcessElement(sKey, hValue);
CloseHandle(hValue);
hIterator = json_object_iter_next(hObj, hIterator);
}
}
Input/Output
Code:
{
"id": "0001",
"type": "donut",
"name": "Cake",
"ppu": 0.55,
"batters":
{
"batter":
[
{ "id": "1001", "type": "Regular" },
{ "id": "1002", "type": "Chocolate" },
{ "id": "1003", "type": "Blueberry" },
{ "id": "1004", "type": "Devil's Food" }
]
},
"topping":
[
{ "id": "5001", "type": "None" },
{ "id": "5002", "type": "Glazed" },
{ "id": "5005", "type": "Sugar" },
{ "id": "5007", "type": "Powdered Sugar" },
{ "id": "5006", "type": "Chocolate with Sprinkles" },
{ "id": "5003", "type": "Chocolate" },
{ "id": "5004", "type": "Maple" }
]
}
Code:
"root"
{
"root"
{
"type" "donut"
"batters"
{
"batter"
{
"0"
{
"id" "1001"
"type" "Regular"
}
"1"
{
"id" "1002"
"type" "Chocolate"
}
"2"
{
"id" "1003"
"type" "Blueberry"
}
"3"
{
"id" "1004"
"type" "Devil's Food"
}
}
}
"id" "0001"
"topping"
{
"0"
{
"id" "5001"
"type" "None"
}
"1"
{
"id" "5002"
"type" "Glazed"
}
"2"
{
"id" "5005"
"type" "Sugar"
}
"3"
{
"id" "5007"
"type" "Powdered Sugar"
}
"4"
{
"id" "5006"
"type" "Chocolate with Sprinkles"
}
"5"
{
"id" "5003"
"type" "Chocolate"
}
"6"
{
"id" "5004"
"type" "Maple"
}
}
"ppu" "0.550000"
"name" "Cake"
}
}
Converting KeyValues to JSON
CODE
PHP Code:
#pragma semicolon 1
#include <sourcemod>
#include <smjansson>
public OnPluginStart() {
// Load some random keyvalues file
new String:sPath[PLATFORM_MAX_PATH];
Format(sPath, sizeof(sPath), "scripts/items/items_game.txt");
new Handle:hKV = CreateKeyValues("");
FileToKeyValues(hKV, sPath);
// Convert it to JSON
new Handle:hObj = KeyValuesToJSON(hKV);
// And finally save the JSON object to a file
// with indenting set to 2.
Format(sPath, sizeof(sPath), "scripts/items/items_game.json");
json_dump_file(hObj, sPath, 2);
// Close the Handle to the JSON object, i.e. free it's memory
// and free the Handle.
CloseHandle(hObj);
}
stock Handle:KeyValuesToJSON(Handle:kv) {
new Handle:hObj = json_object();
//Traverse the keyvalues structure
IterateKeyValues(kv, hObj);
//return output
return hObj;
}
IterateKeyValues(&Handle:kv, &Handle:hObj) {
do {
new String:sSection[255];
KvGetSectionName(kv, sSection, sizeof(sSection));
new String:sValue[255];
KvGetString(kv, "", sValue, sizeof(sValue));
new bool:bIsSubSection = ((KvNodesInStack(kv) == 0) || (KvGetDataType(kv, "") == KvData_None && KvNodesInStack(kv) > 0));
//new KvDataTypes:type = KvGetDataType(kv, "");
//LogMessage("Section: %s, Value: %s, Type: %d", sSection, sValue, type);
if(!bIsSubSection) {
//if(type != KvData_None) {
json_object_set_new(hObj, sSection, json_string(sValue));
} else {
//We have no value, this must be another section
new Handle:hChild = json_object();
if (KvGotoFirstSubKey(kv, false)) {
IterateKeyValues(kv, hChild);
KvGoBack(kv);
}
json_object_set_new(hObj, sSection, hChild);
}
} while (KvGotoNextKey(kv, false));
}
Using json_pack to create JSON
Pack String Rules- n Output a JSON null value. No argument is consumed.
- s Output a JSON string, consuming one argument.
- b Output a JSON bool value, consuming one argument.
- i Output a JSON integer value, consuming one argument.
- f Output a JSON real value, consuming one argument.
- r Output a JSON real value, consuming one argument.
- [<packstring>]
- Build an array with contents from the inner format string.
- Recursive value building is supported.
- No argument is consumed.
- {<packstring>}
- Build an array with contents from the inner format string.
- The first, third, etc. format character represent a key, and must be s (as object keys are always strings).
- The second, fourth, etc. format character represent a value.
- Recursive value building is supported.
- No argument is consumed.
Examples
PHP Code:
// Create an ADT array containing all values
// used in the json_pack string.
new Handle:hParamsArray = CreateArray(8);
PushArrayString(hParamsArray, "String");
PushArrayCell(hParamsArray, 42);
PushArrayCell(hParamsArray, 13.37);
PushArrayCell(hParamsArray, 20001.333);
PushArrayCell(hParamsArray, true);
PushArrayCell(hParamsArray, false);
// Create JSON array with
// 1. element: String
// 2. element: Integer
// 3. element: Float
// 4. element: Float
// 5. element: Boolean
// 6. element: NULL
// 7. element: Boolean
new Handle:hPackArray = json_pack("[sifrbnb]", hParamsArray);
// Create an ADT object containing all values
// used in the json_pack string.
new Handle:hParamsObject = CreateArray(16);
PushArrayString(hParamsObject, "FirstElement");
PushArrayCell(hParamsObject, 1);
PushArrayString(hParamsObject, "SecondElement");
PushArrayCell(hParamsObject, 2);
// Create JSON object with
// "FirstElement": 1
// "SecondElement": 2
// Note: You can omit the ':' and ',', they are just
// for readability.
new Handle:hPackObject = json_pack("{s:i,s:i}", hParamsObject);
// You can obviously nest and mix all of this and
// do something like this:
new Handle:hParams = CreateArray(64);
PushArrayString(hParams, "__String");
PushArrayString(hParams, "What is the \"Hitchhiker's guide to the galaxy\"?");
PushArrayString(hParams, "__Integer");
PushArrayCell(hParams, 9001);
PushArrayString(hParams, "__NestedObject");
PushArrayString(hParams, "__NestedString");
PushArrayString(hParams, "i am nested");
PushArrayString(hParams, "__Array");
PushArrayCell(hParams, 3);
PushArrayString(hParams, "4");
PushArrayString(hParams, "Extension 1");
PushArrayString(hParams, "Extension 2");
new Handle:hPacked = json_pack("{s:s,s:i,s:{s:s,s:[i,s,s,s]}}", hParams);
The last example will result in this:
Code:
{
"__String": "What is the \"Hitchhiker's guide to the galaxy\"?",
"__Integer": 9001,
"__NestedObject": {
"__NestedString": "i am nested",
"__Array": [
3,
"4",
"Extension 1",
"Extension 2"
]
}
}
__________________
einmal mit profis arbeiten. einmal.
Last edited by Thrawn2; 06-24-2012 at 11:50.
|
|