Comments (3)
PR please :)
from frozen.
In my case input JSON is {"ignore": "me"}
(because of #26) and I am calling char *json = "{\"ignore\": \"me\"}"; json_setf(json, strlen(json), &out, ".foo", "{from: %ld, to: %ld, energy: %ld}", rec_start_ts, rec_finish_ts, rec_energy)
.
The result is: {"ignore": "me,"foo":{"from": 1587467683, "to": 1587558755, "energy":
59}"}
from frozen.
I have a fix for this (at least with how I was using it) but don't have the time ATM to do a PR...
Here are the two functions that need to be modified:
static void json_vsetf_cb(void *userdata, const char *name, size_t name_len,
const char *path, const struct json_token *t) {
struct json_setf_data *data = (struct json_setf_data *) userdata;
int off, len = get_matched_prefix_len(path, data->json_path);
int matched = 0;
if (t->ptr == NULL) return;
off = t->ptr - data->base;
// only check matched later on if deliminator or end are found
if (len > data->matched &&
(data->json_path[len] == '.' || data->json_path[len] == '\0')) {
matched = len;
}
/*
* If there is no exact path match, set the mutation position to be end
* of the object or array
*/
if (matched > data->matched && data->pos == 0 &&
(t->type == JSON_TYPE_OBJECT_END || t->type == JSON_TYPE_ARRAY_END))
{
// only save off matched value if it is a new and larger match
data->matched = matched;
// account for a the previous item being a string
if (data->base[data->prev] == '"') {
data->pos = data->end = data->prev + 1;
}
else {
data->pos = data->end = data->prev;
}
}
/* Exact path match. Set mutation position to the value of this token */
if (strcmp(path, data->json_path) == 0 && t->type != JSON_TYPE_OBJECT_START &&
t->type != JSON_TYPE_ARRAY_START) {
// need to set pos and end differently to account for '"' around string
if (t->type == JSON_TYPE_TRUE || t->type == JSON_TYPE_FALSE || t->type == JSON_TYPE_NUMBER) {
data->pos = off;
data->end = off + t->len + 1;
}
else {
data->pos = off - 1;
data->end = off + t->len + 2;
}
data->matched = matched;
}
/*
* For deletion, we need to know where the previous value ends, because
* we don't know where matched value key starts.
* When the mutation position is not yet set, remember each value end.
* When the mutation position is already set, but it is at the beginning
* of the object/array, we catch the end of the object/array and see
* whether the object/array start is closer then previously stored prev.
*/
if (data->pos == 0) {
data->prev = off + t->len; /* pos is not yet set */
} else if ((t->ptr[0] == '[' || t->ptr[0] == '{') && off + 1 < data->pos &&
off + 1 > data->prev) {
data->prev = off + 1;
}
(void) name;
(void) name_len;
}
int json_vsetf(const char *s, int len, struct json_out *out,
const char *json_path, const char *json_fmt, va_list ap) WEAK;
int json_vsetf(const char *s, int len, struct json_out *out,
const char *json_path, const char *json_fmt, va_list ap) {
struct json_setf_data data;
memset(&data, 0, sizeof(data));
data.json_path = json_path;
data.base = s;
data.end = len;
json_walk(s, len, json_vsetf_cb, &data);
if (json_fmt == NULL) {
/* Deletion codepath */
json_printf(out, "%.*s", data.prev, s);
/* Trim comma after the value that begins at object/array start */
if (s[data.prev - 1] == '{' || s[data.prev - 1] == '[') {
int i = data.end;
while (i < len && json_isspace(s[i])) i++;
if (s[i] == ',') data.end = i + 1; /* Point after comma */
}
json_printf(out, "%.*s", len - data.end, s + data.end);
} else {
/* Modification codepath */
int n, off = data.matched+1, depth = 0;
bool empty_base = false;
// if a partial or exact match isn't found, adjust a few items
if (data.matched == 0 && data.pos == 0) {
data.pos = data.prev - 1;
data.end--;
// a completely empty base requres additional correction
if (data.base[0] == '{' && data.base[1] == '}') {
empty_base = true;
data.pos = 1;
data.prev = 1;
data.end = 1;
}
}
/* Print the unchanged beginning */
json_printf(out, "%.*s", data.pos, s);
/* Add missing keys */
while ((n = strcspn(&json_path[off], ".[")) > 0) {
// don't add a comma if it is a completely empty base
if (s[data.prev - 1] != '{' && s[data.prev - 1] != '[' && depth == 0 && !empty_base) {
json_printf(out, ",");
}
if (off > 0 && json_path[off - 1] != '.') break;
json_printf(out, "%.*Q:", n, json_path + off);
off += n;
if (json_path[off] != '\0') {
json_printf(out, "%c", json_path[off] == '.' ? '{' : '[');
depth++;
off++;
}
}
/* Print the new value */
json_vprintf(out, json_fmt, ap);
/* Close brackets/braces of the added missing keys */
for (; off > data.matched; off--) {
int ch = json_path[off];
const char *p = ch == '.' ? "}" : ch == '[' ? "]" : "";
json_printf(out, "%s", p);
}
/* Print the rest of the unchanged string */
json_printf(out, "%.*s", len - data.end, s + data.end);
}
return data.end > data.pos ? 1 : 0;
}
from frozen.
Related Issues (20)
- How to parse large string HOT 1
- Some bugs in frozen
- json_scanf does not work when the key is an integer HOT 2
- json_printf_array with "%f" does not work
- Can't parse json array HOT 1
- json_scanf: only first object gets parsed HOT 1
- JSON5-style Comments?
- Advice for using it with 8-bit AVR MCU
- Scanf string using scanset (character class)
- Print array of structs to JSON (or nested/twodimensional array) HOT 1
- frozen 1.6 with Apache commons 2.0 dual licence HOT 4
- Invalid licence header in unit_test.c HOT 1
- frozen release with Apache License, Version 2.0
- Lots of cppcheck warnings
- Difference between MJSON and Frozen? HOT 3
- json_sprinter reduce number of reallocations HOT 1
- how to handle nested json HOT 1
- Function json_vfprintf convert {"three":2,"two":2,"one":2} to {""three"":1,""two"":1,""one"":1}
- Release a new version
- Missing entry if key-name ends with dot
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from frozen.