C: How to parse a value from Json request? - c

I am attempting to use the cJSON library, written by Dave Gamble, to read in the following JSON request:
{"id":"8358441244995838759","jsonrpc":"2.0","method":"addext",
"params":["<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>
<trunks id=\"0\"><end_ch>3</end_ch>
<gateway>172.20.222.52</gateway>
<interface_type>E231</interface_type>
<name>Mumbai_Avaya</name>
<start_ch>12</start_ch>
<sub_type>E1PRI</sub_type></trunks>"]}
I am able to retrieve the "id" and "method" by using below code, but not able to retrieve or print the values inside "params" which is an XML string.
I want to print whatever inside the "params".
cJSON *cjson, *method_obj;
char *methodname;
char *params;
cjson = cJSON_Parse(buf);
method_obj = cJSON_GetObjectItem(cjson, "method");
methodname = method_obj->valuestring;
printf("method name %s\n", methodname);
method_obj = cJSON_GetObjectItem(cjson, "id");
id = method_obj->valueint;
char *str = method_obj->valuestring;
printf("id %s\n", str);
method_obj = cJSON_GetObjectItem(cjson, "params");
params=method_obj->valuestring;
printf("Params [ ] %s\n", params);
Please provide any suggestion.
Thanks in Advance.

Either change method_obj->valuestring to method_obj->child->valuestring (after checking that child != NULL), or have the service, that generates the JSON request, not use an array if none is needed.

params of field type is JSON Array.
use cJSON_GetArrayItem (and cJSON_GetArraySize) API like this:
method_obj = cJSON_GetObjectItem(cjson, "params");
int size = cJSON_GetArraySize(method_obj);
for(int i = 0; i < size; ++i){
params = cJSON_GetArrayItem(method_obj, i)->valuestring;
printf("Params [ ] %s\n", params);
}

Related

JSON object is incorrectly decoded as JSON String(Parson library)

I'm using the parson library to decode a json message body sent from a backend (AzureIoTHub direct method call). My string is always decoded as type JSONString instead of JSONObject so I cannot extract and keys and values. I think something is wrong with my string in the payload buffer but I'm stuck on what it is. ANy help is appreciated.
Here are two examples of different json strings stored in payload_buffer variable and neither work.
"{'device': '65'}"
JSON Type: 2
or
"{"device": "3445667"}"
JSON Type: 2
uint8_t payload_buffer[448];
JSON_Value *root_value = NULL;
JSON_Object *root_object = NULL;
JSON_Value *device_name = NULL;
const char* device;
printf("%.*s \r\n", (INT)insert_index, (CHAR *)&payload_buffer );
root_value = json_parse_string((const char *)&payload_buffer[0]);
if (root_value != NULL)
{
if (json_value_get_type(root_value) == JSONObject)
{
root_object=json_value_get_object(root_value);
device_name = json_object_dotget_value (root_object, "device");
device = json_value_get_string(device_name);
if (device != NULL)
{
printf("device: %s", device );
}
}
else
{
printf("JSON Type: %u \r\n", json_value_get_type(root_value));
}
}
For parson library to interpret a buffer as a JSONObject and not a JSONString you cannot have the buffer start and end with " character. Once I edited my buffer to this
{"device": "3445667"}
my code was able to parse the JSON object correctly.

convert from CSIdentity to a C-compatible string

Intro
I have an objective-C file (.m) in which I'm trying to query local users (through CSGetLocalIdentityAuthority and then print each user via printf (intentionally using C).
What do I expect?
get local users with objective c, print them with C pritnf.
Here's my attempt:
main.m
int main(){
// Query Local Identity Authority
CSIdentityAuthorityRef defaultAuthority = CSGetLocalIdentityAuthority();
CSIdentityClass identityClass = kCSIdentityClassUser;
CSIdentityQueryRef query = CSIdentityQueryCreate(NULL, identityClass, defaultAuthority);
CFErrorRef error = NULL;
CSIdentityQueryExecute(query, 0, &error);
// get query results
CFArrayRef users_queried = CSIdentityQueryCopyResults(query);
//iterate over users
// Create a users array
NSMutableArray * users_list = [NSMutableArray array];
// // number of users
int users_queried_count = CFArrayGetCount(users_queried);
// // iterate users and save to users array
for (int i = 0; i < users_queried_count; ++i) {
CSIdentityRef identity = (CSIdentityRef)CFArrayGetValueAtIndex(users_queried, i);
CBIdentity * identityObject = [CBIdentity identityWithCSIdentity:identity];
[users_list addObject:identityObject];
}
for (NSString *user in users_list) {
// NSLog(#"%#", user);
const char *c_user = [user UTF8String];
printf("%s", c_user);
}
// release
CFRelease(users_queried);
CFRelease(query);
return 0;
}
However, this yeilds the following error:
*** Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: '-[CBUserIdentity UTF8String]:
unrecognized selector sent to instance 0x7fac024161f0'
You can see I'm trying to convert the NSString to a UTF8 String and print it, but it fails (however, NSLogging' it works).
CBIdentity is not a NSString - its a CBIdentity!
If you print it using NSLog it gets converted to a string (through description), but if you message it with UTF8String as you do it does not work.
You've commented out NSLog(#"%#", user);
If that actually gives you what you want then change the add part to
[users_list addObject:[identityObject description]];
Otherwise, note that you are looping CBIdentity and not NSString so change the loop e.g. like so or similar.
for ( CBIdentity * user in users_list ) {
const char *c_user = [[user posixName] UTF8String];
printf("%s", c_user);
}
There is a -fullName property for the class

How to find text inside an array from a json file?

I have a json array called "names". I want to prevent repeating the same name by searching it before it is entered on the array.
I find this code, but i need also to run the function enterName if the name is not repeated.
Thnaks
var name = "TEST";
for (var i = 0; i < config.names.length; i++){
if (config.names[i] == name){
console.log("name repeated");
}
}
Try this
if (!config.names.find(p=>p===name))
enterName(name);
Using ES7
const name = "TEST";
if (!config.names.includes(name)) {
enterName(name);
}

Unable to access first data item in JSON Array

I'm having trouble pulling a piece of data from a JSON array. I believe I've tried every answer from similar posts here but I'm missing something. I've imported the org.JSON library. Here is my JSON text:
{
"symbol":"AAPL",
"earnings":[
{
"actualEPS":2.34,
"consensusEPS":2.17,
"estimatedEPS":2.17,
"announceTime":"AMC",
"numberOfEstimates":10,
"EPSSurpriseDollar":0.17,
"EPSReportDate":"2018-07-31",
"fiscalPeriod":"Q3 2018",
"fiscalEndDate":"2018-06-30",
"yearAgo":1.67,
"yearAgoChangePercent":0.40119760479041916,
"estimatedChangePercent":0.29 940119760479045,
"symbolId":11
},
{
"actualEPS":2.73,
"consensusEPS":2.69,
...
...
}
]
I'm trying to read the first instance of "actualEPS", there are a total of four in the array. My code currently looks like this:
String jsonIn = sb.toString();
JSONArray earningsArray = new JSONArray(jsonIn);
double eps = 0;
for(int i = 0; i < earningsArray.length(); i++) {
JSONObject jObject = earningsArray.getJSONObject(i);
eps = jObject.getDouble("actualEPS");
} // end for loop
System.out.println("This is the first instance of EPS: " + eps);
The StringBuilder (sb) in the first line is my JSON and prints out correctly in the console just ahead of this block.
The stack trace shows the error in this line:
JSONArray earningsArray = new JSONArray(jsonIn);
The error I'm getting is
"A JSONArray text must start with '[' at 1 [character 2 line 1]"
I've never used JSON prior to now and am not sure what my error is exactly. I tried shortening the String going into the array to begin with just the array opening bracket but that didn't work either. I feel like I'm missing something simple. Where have I gone wrong?
You need to understand there are two types of datastructure in a JSON.
first is Object which always starts with '{' and ends with '}'
second is Array which always starts with '[' and ends with ']'
JsonArray is nothing but an array of JsonObject means a json array will always look like
"jsonarray":[
{
//json object
},
{
// json object
}
]
hope now you understand how json works
now come to your json
{ // jsonObjectParent Starts
"symbol":"AAPL",
"earnings":[ // jsonArray Starts
{ //jsonObject1 Starts
"actualEPS":2.34,
"consensusEPS":2.17,
"estimatedEPS":2.17,
"announceTime":"AMC",
"numberOfEstimates":10,
"EPSSurpriseDollar":0.17,
"EPSReportDate":"2018-07-31",
"fiscalPeriod":"Q3 2018",
"fiscalEndDate":"2018-06-30",
"yearAgo":1.67,
"yearAgoChangePercent":0.40119760479041916,
"estimatedChangePercent":0.29 940119760479045,
"symbolId":11
}, // jsonOject1 Ends
{ //jsonObject2
"actualEPS":2.73,
"consensusEPS":2.69,
...
...
}
] //jsonArray Ends
} //jsonObjectParent Ends
So here if you want to parse this json you have to first parse it in a jsonObject as you seen above
JsonObject jsonObjectParent = new JsonObject(jsonIn);
// here jsonobject contains json array so etract it like this
JsonArray jsonArray = jsonObjectParent.getJsonArray("earnings");
//now you can access the values here
JsonObject jsonObject1 = jsonArray.getJsonObject(0); // here 0 means first jsonObject in array if you want all you can make a loop here
string actualEps = jsonObject1.getDouble("actualEPS");
Hope now you understands the concept of how JSON Works
please let me know is this solution worked
Do this :
JSONObject json = new JSONObject(response);
JSONArray data = json.optJSONArray("earnings");
for (int i = 0; i < data.length(); i++) {
JSONObject jsonObject1 = data.getJSONObject(i);
Double actualEPS = jsonObject1.getDouble("actualEPS");
Double consensusEPS = jsonObject1.getDouble("consensusEPS");
Double estimatedEPS= jsonObject1.getDouble("estimatedEPS");
String announceTime = jsonObject1.getString("announceTime");
int numberOfEstimates = jsonObject1.getInt("numberOfEstimates");
Double EPSSurpriseDollar= jsonObject1.getDouble("EPSSurpriseDollar");
String EPSReportDate= jsonObject1.getString("EPSReportDate");
String fiscalPeriod= jsonObject1.getString("fiscalPeriod");
String fiscalEndDate= jsonObject1.getString("fiscalEndDate");
Double yearAgo= jsonObject1.getDouble("yearAgo");
Double yearAgoChangePercent= jsonObject1.getDouble("yearAgoChangePercent");
Double estimatedChangePercent = jsonObject1.getDouble("estimatedChangePercent");
int symbolId = jsonObject1.getInt("symbolId");
}
#Driver8, the JSON earninsArray is a single JSON object and not an array of JSON objects. Your basic idea here is alright everywhere excpet for just that line. Instead of instantiating a JSON array, instantiate a JSON OBJECT.
Should be something like this:
String jsonIn = sb.toString();
JSONObject earningsObject = new JSONObject(jsonIn);
JSONArray earningsArray = earningsObject.getJSONArray("earnings");
double eps = new double(earningsArray.length());
for (int i = 0; i < earningsArray.length(); i++) {
JSONObject j1 = earningsArray.getJSONObject(i);
eps[i] = j1.getDouble("actualEPS");
}
All the values of actualEPS will be stored as per their order in the array declared to store the EPS values.
Hope this helps.

azure-iot-sdk-c deserialize JSON payload

I'm getting started with the Azure IoT SDK C-Library by using the IoT_Hub Device Method samples.
Does anybody know if the SDK provides a function to deserialize the JSON message payload? There are some good examples for payload serialization to JSON, but I wasn't able to find the counterpart.
I'm quite sure the SDK has some functionalities for JSON deserialization, e.g. something like:
BEGIN_NAMESPACE(WeatherStation);
DECLARE_MODEL(ContosoAnemometer,
WITH_DATA(ascii_char_ptr, DeviceId),
WITH_DATA(int, WindSpeed),
WITH_DATA(float, Temperature),
WITH_DATA(float, Humidity),
WITH_ACTION(TurnFanOn)
);
END_NAMESPACE(WeatherStation);
static int DeviceMethodCallback(const char* method_name, const unsigned char* payload, ...)
{
(void)userContextCallback;
ContosoAnemometer* myWeather = CREATE_MODEL_INSTANCE(WeatherStation, ContosoAnemometer);
DESERIALIZE(myWeather, payload)
printf("Device Id: %i\r\n", myWeather->DeviceId);
// etc. etc.
}
In the Azure IoT SDK for C,it uses serializer library to serialize messages to send, but there is no couterpart(DESERIALIZE) for receiving messages.Please see
more about serializer. In serializer component, you will find jsondecoder.c, it defines some method for decode json data.
And more, you will find the parson component. It can be used to deserialize the object from json string.You can refer to the following code.
jsonstr
{"desString":"P7svG%2BLoUZEbB8Le5jP1%2BpuX2OVWLE4xWMzFcYFCRvNvDlcFVm%2B8z2VFO%2F%2BaEB8UAMa%2FZ0GGhooGNMWFE98Zmw%3D%3D","caller":{"mobile":"13996130361"},"accountId":"b5091dc91d700c6bf714e5fc446797d3","tmpTime":1428545890,"otherParam":"{id:12}","participant":[{"mobile":"18623582801"}],"servletUrl":"http://192.168.1.1:8090/xdr"}
C Code
JSON_Value *root_value=NULL;
root_value = json_parse_string(jsonstr);
JSON_Object *root_object;
if(json_value_get_type(root_value) == JSONObject)
{
root_object = json_value_get_object(root_value);
const char *desString = json_object_get_string(root_object, "desString");
if(desString!=NULL)strncpy(pPost->desString,desString,LENGTH128-1);
const char *accountId = json_object_get_string(root_object, "accountId");
if(accountId!=NULL)strncpy(pPost->accountId,accountId,LENGTH32);
double tmpTime = json_object_get_number(root_object, "tmpTime");
const char *caller = json_object_dotget_string(root_object,"caller.mobile");
if(caller!=NULL)strncpy(pPost->caller,caller,LENGTH16-1);
const char *servletUrl = json_object_dotget_string(root_object,"servletUrl");
if(servletUrl!=NULL)strncpy(pPost->servletUrl,servletUrl,LENGTH128-1);
const char *otherParam = json_object_dotget_string(root_object,"otherParam");
if(otherParam!=NULL)strncpy(pPost->otherParam,otherParam,LENGTH128-1);
JSON_Array *array;
array = json_object_get_array(root_object, "participant");
int i =0;
for(i;i<json_array_get_count(array);i++)
{
JSON_Object *tmp = json_array_get_object(array,i);
if(tmp!=NULL)
{
const char *mobile = json_object_get_string(tmp,"mobile");
if(mobile!=NULL)strncpy(pPost->callee,mobile,LENGTH16-1);
}
}
}
if(root_value)json_value_free(root_value);

Resources