5 ms·
Show HN: Parson, lighweight json parser in C
- bengl3rt 14y agoHmm, looks complex compared to this one that I've been using called JSMN: http://zserge.bitbucket.org/jsmn.html http://zserge.bitbucket.org/jsmn.html
- kgabis 14y agojsmn is more of a lexer and it doesn't support unicode.
- udp 14y agoHave you really been using jsmn for something or did you just recall the link? IMHO jsmn doesn't do nearly enough with the JSON to make it usable by an application (it's basically a lexer).
- hendi_ 14y agojsmn is great if you use it as a lexer and you know that your input is well-formed. We use it for our games to read in our configuration, gamemodes and level files. We've just built a few wrapper functions around jsmn and called it "jsmx", and it suits our needs perfectly :-) But you're right, if you want a json library to parse arbitrary json input using a more complex library like this one is the easier and more viable route than using jsmn.
- DrCatbox 14y agoWhats the thing with saying "Only 2 files" what if it is only 1 file, like bottle.py, but the 1 or 2 files contain 10 000 lines of code? Im just saying.
- pi18n 14y agoYeah, seriously. I just did some work with the s7 implementation of Scheme. "Only two files!" I think in all fairness, I think the idea is that you should just drop it in your source without needing to worry about git subrepos (or whatever). But it would be perhaps more elegant to split it up in the repo and have a script stitch it together into the "only two files". Also s7 turned out to be much easier to include than the other ones I was considering, so I guess I shouldn't be mocking it.
- mhd 14y agoWell, as in the case with bottle, it's probably meant to imply that you can just use it in your project as files, not as a complete library. No need to complicate your Makefiles (or worry about your package framework).
- eps 14y agoparson.c, 109 - wrong conditional Well-written, clean and consistent. A bit too pendantic and therefore too verbose for my taste though :) Why in KnR's name this - JSON_Object *new_obj = (JSON_Object*)parson_malloc(sizeof(JSON_Object)); is not written like this - JSON_Object *new_obj = parson_malloc(sizeof *newobj); On a more serious note - I would move json_*_t structs to the header file and eliminate a bunch of API functions that service the access to these structs. It's a C library after all, everyone knows how to shoot one's own leg. (edit) Oh, and you don't handle realloc failures properly (at least in json_object_add).
- deleted 14y ago[deleted]
- kgabis 14y agoThanks for pointing out those errors, I already fixed the one with the wrong conditional and will fix the realloc one in the next commit. I'm being explicit with casting, because g++ and vc++ will throw warnings without it.
- eps 14y agoOf course you'd get warnings compiling C code with C++ compiler. C doesn't require casting from void* to another pointer type... it's one of its best features :)
- malkia 14y agoCertain people would still like to compile this as a "CPP" file, examples are lua - it's in "C", but it's compilable as C++ too (some people then are more or less strict whether the function interfaces should be extern"C" or not). Ayway, not that important... But there is a whole lot of people that like amalgated sources (typical examples - juce, freetype2, lua, sqlite) where you include in one or two files all the rest and they compile fine.
- cmccabe 14y ago
- udp 14y agoWell, you beat json-parser on SLOC. :-) Main differences are that you use recursion instead of a stack, and that you dynamically resize your buffers as you parse (whereas json-parser passes through the JSON twice so that it knows exactly how much memory to allocate).
- isbadawi 14y agoHow does this compare to jansson (http://www.digip.org/jansson/ http://www.digip.org/jansson/), aside from just being a parser?
- __david__ 14y agoThanks, I've been looking for something like this for a project I have (https://github.com/caldwell/daemon-manager https://github.com/caldwell/daemon-manager). I did a survey of all the JSON libs for C and C++ about a year ago and found reasons to dislike them all. This actually looks like a reasonable interface, the code itself looks good so far, and I love the fact that it is just a couple files I can drop in.
- udp 14y agoJust out of curiosity, was json-parser one of the ones you looked at? If so, what did you dislike about it?
- __david__ 14y agoNo, I haven't seen that one (looks like you wrote it?). I was looking for them at the tail end of 2011 and it looks like json-parser came into existence in march, 2012. json-parser, at first glance, appears to be nice, too. The ones I looked at before were all multiple files and seemingly very complicated--either to use or to build/integrate with my code. I'll keep a pointer to this one too for when I get back on that project.
- IgorPartola 14y agoI've been using http://cjson.sourceforge.net/ http://cjson.sourceforge.net/ for a while. Single file, reasonable interface. It lets you both serialize and de-serialize JSON. Was this a library you looked at when you did your survey?
- d0mine 14y agoLooking at the source It seems it doesn't handle surrogate pairs e.g., ["\ud83d\ude04"]
- kgabis 14y agoYou're right, I'll try to add support for them in the future.
- halayli 14y agoyou are calling realloc and assigning the value directly before checking the return value. realloc can fail and return NULL and you'll overwrite the previous pointer which will cause a memory leak. I don't see why you duplicated strndup in parson_strndup. https://github.com/kgabis/parson/blob/master/parson.c#L129 https://github.com/kgabis/parson/blob/master/parson.c#L129 parson_strdup can return NULL and this statement will fail silently.
- thomaslee 14y agostrndup is part of the "standard", but not present on some platforms unfortunately. :( I can't think of a modern C runtime that doesn't offer strdup, though. The realloc check is good advice -- take heed, OP. :)
- halayli 14y agoTrue, strndup is relatively new (~7 years) to POSIX standard.
- kgabis 14y agoRealloc, strdup and strndup errors are handled as of now :) (https://github.com/kgabis/parson/commit/ee9be98974b3fdac0be1cc370bec948613e725d7 https://github.com/kgabis/parson/commit/ee9be98974b3fdac0be1...) And yes, I've written my own strndup because it's "relatively new".
- zokier 14y agoThat style of C programming makes me immediately think how it would be neater in C++. Eg the frontpage example: https://gist.github.com/3969351 https://gist.github.com/3969351 Key differences: * actual namespaces, no need to prefix everything with "JSON_" * RAII-style resource management, no need for "json_value_free" etc * objects, so instead of get_array(root_value) you have root_value.get_array()
- huhtenberg 14y ago> json::Array commits = root_value.get_array(); You probably meant: json::Array & commits = root_value.get_array(); Don't really want to copy an array there, right? After that you'll probably be tempted to use std::vector as a basis for json::array. Then you'll realize what an abysmal PoS default vector allocator is, and so you'd want to allow customizing it. Hello templates, and then before you know it, the whole thing not only looks like one of them incomprehensible boost beauties, but also compiles into a meg of code with a dozen dependencies. Neat :)
- zokier 14y ago> After that you'll probably be tempted to use std::vector as a basis for json::array. Then you'll realize what an abysmal PoS default vector allocator is, and so you'd want to allow customizing it. Hello templates, and then before you know it, the whole thing not only looks like one of them incomprehensible boost beauties, but also compiles into a meg of code with a dozen dependencies. Neat :) Writing good code means having discipline to resist all sorts of temptations, such as the one you describe. And not all slippery slopes are actually all that slippery. The one good thing about C++ is that you can pick the features you want and mostly ignore the rest. The reason C++ is so humungous is that everyone is using different subset of it.
- huhtenberg 14y ago> The reason C++ is so humungous is that everyone is using different subset of it. I completely agree with this. Incidentally, this is exactly the reason why C++ libraries are far less useful than the C ones.
- cmccabe 14y agoI'm aware of a few different JSON parsing libraries for C. * Metaparadigm's "JSON-C" library (see https://github.com/json-c/json-c/wiki https://github.com/json-c/json-c/wiki) * Jansson (see http://www.digip.org/jansson/ http://www.digip.org/jansson/) * yajl (see http://lloyd.github.com/yajl/ http://lloyd.github.com/yajl/) All of those are licensed extremely permissively (BSD, ISC, etc) yajl seems kind of SAX-like, which I'm not really a big fan of, but I guess some people might like it. It would be good if you had a humungous JSON stream, for the same reasons SAX beats DOM in those cases. json-c and Jansson seem pretty similar to me. Jansson seems to be more full-featured than json-c, with stuff like a json_equal method, a json_deep_copy method, and the ability to specify custom memory allocation functions. But for most use cases there isn't too much difference between the two. So I guess my question is really what is the use case you're targeting? It would be nice to have some context about what you see as the niche you're filling.