Adding Unique Elements to a Json Object using C - c

Using (learning) c to create a mini packet sniffer which adds the src IPs to a json object and adds them to a json array.
The pcap filter works without issue, and now I'm trying to create a json object of the src ips and a counter of packets sent to this IP.
{
"ips": [
{
"ip": "1.2.3.4",
"count": 10
},
{
"ip": "4.3.2.1",
"count": 103
}
]
}
Excluding all the pcap code, I have a loop as so:
pcap_loop(pcap, 1000, ethernet_packet, NULL);
Within the ethernet_packet function, I created an array for the IPs so I could check if one had already been added.
if (!array_contains(buf, src_ip)) {
// Do things
}
int array_contains(char *array, char *ip ) {
if ( strchr(array, *ip) )
return 1;
}
Here's what I have so far which was supposed to get the IP and add to the array:
void ethernet_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet)
{
static int count = 1;
printf("\nPacket number %d:\n", count); */
count++;
struct json_object *obj1, *obj2, *array;
array = json_object_new_array();
obj1 = json_object_new_object();
char buf[MESSAGE_BUFF_LEN];
/* Some Pcap stuff to get the ips etc. */
src_ip = inet_ntoa(ip->ip_src);
if (!array_contains(buf, src_ip)) {
/* Add IP to array */
sprintf(buf, src_ip);
/* Create a new object */
obj2 = json_object_new_object();
json_object *jstring = json_object_new_string(src_ip);
json_object_object_add(obj2,"ip", jstring);
/* Add to array */
json_object_array_add(array,obj2);
}
}
The problem I have is that the object isn't added to an existing array, it creates a new one each time.
The json object created: [ { "ip": "79.65.10.0" } ]
The json object created: [ { "ip": "80.152.10.0" } ]
The json object created: [ { "ip": "99.211.10.0" } ]
I even tried checking the type of object at the start of the loop and only initialising when it was not an array but that threw an error when trying to add.
It's probably obvious to someone who's spent more than 2 days with c but I don't understand how to fix this.
What's the best / most efficient way to solve this?
--- EDIT ---
Have it working by checking the type and initialising if it's not an array. Just not sure this is the best way to do so.
Full code for the fn is here:
https://gist.github.com/simonmorley/9850f2a42453e4f54b75

This is wrong
char buf[MESSAGE_BUFF_LEN];
/* Some Pcap stuff to get the ips etc. */
src_ip = inet_ntoa(ip->ip_src);
if (!array_contains(buf, src_ip)) {
because buf is initialized with garbages, as it is local variable, so doing strchr on its content is not what you want.
Additionally, it seems like you are not adding the object to correct array:
/* Add to array */
json_object_array_add(res,obj2);
// ^^^

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.

Handling Null JSON Array in Go using struct

we have struct and getting null after append struct in golang.
Find below struct with my some part of code in golang.
type XmloutRoomRate struct {
CancellationPolicy Policies `bson:"cancellationPolicy" json:"cancellationPolicy"`
}
type Policies struct {
Policies []RoomPolicies `bson:"policies" json:"policies"`
}
type RoomPolicies struct {
Amount float64 `bson:"amount" json:"amount"`
DaysBeforeCheckIn int `bson:"daysBeforeCheckIn" json:"daysBeforeCheckIn"`
}
cancelPolicyMain := Policies{}
cancelPolicy := RoomPolicies{}
if cancelAmount < 0 {
cancelPolicy.Amount = cancelAmount
cancelPolicy.DaysBeforeCheckIn = cancelDay
cancelPolicyMain.Policies = append(cancelPolicyMain.Policies, cancelPolicy)
}else{
cancelPolicyMain = agodaPolicies{}
cancelPolicyMain.Policies = append(cancelPolicyMain.Policies)
}
when data present getting proper data structure.
"cancellationPolicy": {
"policies": [
{
"amount": 5141.58,
"daysBeforeCheckIn": 5
}
]
}
But when data not available getting struct with null value.
"cancellationPolicy": {
"policies": null
}
We need my actual output with blank array [].
"cancellationPolicy": {
"policies": []
}
nil slice values are marshaled into JSON null values. This is documented at json.Marshal():
Array and slice values encode as JSON arrays, except that []byte encodes as a base64-encoded string, and a nil slice encodes as the null JSON value.
Non-nil empty slices are marshaled into empty JSON arrays. So simply initialize Policies.Policies to a non-nil empty slice, and it will be [] in the output:
cancelPolicyMain = Policies{Policies: []RoomPolicies{}}
Test code:
const cancelDay = 1
for cancelAmount := -500.0; cancelAmount <= 501; cancelAmount += 1000 {
cancelPolicyMain := Policies{}
cancelPolicy := RoomPolicies{}
if cancelAmount < 0 {
cancelPolicy.Amount = cancelAmount
cancelPolicy.DaysBeforeCheckIn = cancelDay
cancelPolicyMain.Policies = append(cancelPolicyMain.Policies, cancelPolicy)
} else {
cancelPolicyMain = Policies{Policies: []RoomPolicies{}}
cancelPolicyMain.Policies = append(cancelPolicyMain.Policies)
}
x := XmloutRoomRate{cancelPolicyMain}
if err := json.NewEncoder(os.Stdout).Encode(x); err != nil {
panic(err)
}
}
Output (try it on the Go Playground):
{"cancellationPolicy":{"policies":[{"amount":-500,"daysBeforeCheckIn":1}]}}
{"cancellationPolicy":{"policies":[]}}
In an array, the meaning of a "null" entry is clear: It means this array entry is missing.
In an object aka dictionary, there are different ways to indicate "no entry": The key might not be there. Or the key might not be there, but with an empty array as value. Or the key might be there, but with a "null" value.
You really need agreement between the provider of the data and the client processing it, what each of these mean. And since it's often hard to change what the data provider does, translate what you get into what you need.
So you have to decide what it means if "policies" does not exist as a key, or if it exists as a null value. I've seen software that wouldn't produce arrays with one element, but would provide the single element instead. So "policies": { "amount": ..., "daysBeforeCheckin": ... } would also be possible. You decide what you accept, what you treat as an array, and how you change from the form you got to the form you want.

flutter get json array

Hi I have this JSON as a string as a response for an API call
{
"friends": {
"data": [],
"summary": {
"total_count": 42
}
},
"id": "111111111111111"
}
I want to get friends.data and friends.summary.total_count.
Something like :
for (int i = 0 ; i < friends.summary.total_count ; i++)
{
myAmazingArray.pushback(friends.data[i]);
}
I think that total_count is the number of contents in the array.
I also know that in order to get the "id" I have to do : json['name']
You need to use jsonDecode from dart:convert. Actually you don't even need to use the total_count value at all, if the length in data is the same. You can simply use:
import 'dart:convert';
final Map<String, dynamic> dataMap = jsonDecode(json);
final List<dynamic> friendsData = dataMap['friends']['data'];
for(dynamic friend in friendsData) myAmazingArray.pushback(friend);
I don't know what kind of content is contained in data, so I suggest you to find out the runtime type (e.g. String, Map etc.) and exchange the word 'dynamic' in my code above to improve the code quality.
If you wanted to do it with total_count:
final int total_count = dataMap['friends']['summary']['total_count'];
for(int i=0; i<total_count; i++)
myAmazingArray.pushback(friendsData[i]);

C: How to parse a value from Json request?

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);
}

Getting list elements from Prolog in a C interface

I try to implement a C interface using a Prolog script based on GNU Prolog. My problem is to get single elements of a nested Prolog list.
Actually my C code looks like
...
int func;
PlTerm arg[10];
PlTerm *sol_gb;
PlBool res;
int nmb;
char *strHead;
char *strTail;
PlLong nummero;
PlTerm pl_nummero;
Pl_Start_Prolog(argc, argv);
Pl_Query_Begin(PL_TRUE);
arg[0] = Pl_Mk_String(strRName);
arg[1] = Pl_Mk_Variable();
arg[2] = Pl_Mk_Variable();
arg[3] = Pl_Mk_String("true");
res = Pl_Query_Call(func, 4, arg);
sol_gb = Pl_Rd_List(arg[2]);
nmb = Pl_List_Length(sol_gb[0]);
strHead = Pl_Write_To_String(sol_gb[0]);
printf("strHead = %s\n",strHead);
strTail = Pl_Write_To_String(sol_gb[1]);
printf("strTail = %s\n",strTail);
...
The Prolog list returned in arg[2] looks like
[ [ Spezial Bolognese,
[2, ,Zwiebeln,300,gramm,Hackfleisch,10, ,Tomaten,
100,ml,Sahne,500,gramm,Spaghetti]
],
[ Spaghetti Bolognese,
[2, ,Zwiebeln gehackt,300,gramm,Hackfleisch,10, ,Fleischtomaten,
100,ml,Sahne,500,gramm,Spaghetti]
]
]
The output of the conversion into a String is
strHead = [Spezial Bolognese,[2, ,Zwiebeln gehackt,300,gramm,Hackfleisch,
10, ,Fleischtomaten,100,ml,Sahne,500,gramm,Spaghetti]]
strTail = [[Spaghetti Bolognese,[2, ,Zwiebeln gehackt,300,gramm,Hackfleisch,
10, ,Fleischtomaten,100,ml,Sahne,500,gramm,Spaghetti]]]
So I assume, I am "nearly there" but as I have to re-activate my C knowledge I do not get the solution how to enter in the next level of the list to get finally each element as string ("Spezial Bolognese", next step: "2", "Zwiebeln" etc.).
How can I step through the Prolog list in C?
I would be very happy about every hint, thank you again!
To get the content of a list from the C-code you can use 2 kind of functions.
First possibility (simple since the list is seen as a flat object but requires more memory and needs a proper list, i.e. does not work for lists not terminated by [])
int Pl_Rd_Proper_List_Check(PlTerm the_prolog_list, PlTerm *the_array_receiving_arguments);
this functions receives an array (it is up to you to ensure it is large enough), stores each element of the list in the array and returns the total number of elements. Example:
PlTerm list = ...some Prolog list...
int nElem = Pl_List_Length(list);
PlTerm *elem = (PlTerm *) calloc(nElem, sizeof(PlTerm));
Pl_Rd_Proper_List_Check(list, elem);
int i;
for(i = 0; i < nElem; i++) {
// here there is an argument in elem[i], let's print it
Pl_Write(elem[i]);
}
Second possibility (more general but see a list as a chained list, each cell contains the head and a tail (a list))
PlTerm *Pl_Rd_List(PlTerm the_prolog_list);
This function returns an array of 2 elements corresponding to the head and the tail of the received list. This function should be called on each element of the list; either you know the number of elements or you test the end of the list (e.g. waiting for the end of list atom []). Here is a code doing this (it is expected to be inside the above loop since we know the second argument of the list is a nested list.
PlTerm list = ... some Prolog list...;
while(!Pl_Un_Atom(Pl_Atom_Nil(), list)) {
PlTerm *lst_arg = Pl_Rd_List(list); // [0] = head element, [1] = tail list
// here there is an argument in lst_arg[0], let's print it
Pl_Write(lst_arg[0]);
list = lst_arg[1];
}
In your example, the first list looks like:
[ 'Spezial Bolognese',
[2,' ','Zwiebeln',
300,'gramm','Hackfleisch',
10,' ','Tomaten',
100,'ml','Sahne',
500,'gramm','Spaghetti']
]
so the second element is a nested list. The following code uses the first method for the above list (which has 2 elements), and the second method for the nested list:
nElem = Pl_List_Length(sol_gb[0]);
PlTerm *elem = (PlTerm *) calloc(nElem, sizeof(PlTerm));
Pl_Rd_Proper_List_Check(sol_gb[0], elem);
int i;
for(i = 0; i < nmb; i++) {
if (i != 1) {
Pl_Write(elem[i]);
printf("\n");
} else { // we know it is a list
printf("(");
PlTerm list = elem[i];
while(!Pl_Un_Atom(Pl_Atom_Nil(), list)) {
PlTerm *lst_arg = Pl_Rd_List(list); // [0] = head element, [1] = tail list
printf(" ");
Pl_Write(lst_arg[0]);
list = lst_arg[1];
}
printf(" )\n");
}
}
Here should be the output
Spezial Bolognese
( 2 Zwiebeln 300 gramm Hackfleisch 10 Tomaten 100 ml Sahne 500 gramm Spaghetti )
The sample code you give of the lists of lists sounds like a textbook example of a very bad choice for knowledge representation. I strongly suggest you change it to a more declarative representation. Something like:
% pizza(Name, Steps)
pizza('Spezial Bolognese', ...).
...
where Steps could be a list of step(...) terms. This would potentially make processing the information easier and more efficient. For example, in the Prolog side, you could then use the standard arg/3 predicate to access a specific element in a step. With lists, you have no choice other than traversing them every time you want an element other than the list head.

Resources