在C中使用YAJL解析json
我一定做错了什么......或者这可能是 YAJL 中的一个错误,但我非常怀疑这一点。 我无法从 json 对象中检索第一个元素。我回到 YAJL 源代码并使用示例 parse_config.c 对此进行测试,但它也失败了。
使用sample.config,
/*
* The configuration file for Yahoo! BrowserPlus, included in the YAJL
* tree as a sample configuration file for parsing.
*
* This is the configuration file for BrowserPlus
*/
{
// The type of build this is, which is accessible to JavaScript via
// BrowserPlus.getPlatformInfo();
// Different build types should only differ in signatures accepted
// (BrowserPlus.crt) and configured distribution servers.
"BuildType": "ephemeral",
// the base url for the "primary" distribution server. This server will
// be the single source of truth for Permissions, and will used to
// attain services
"DistServer": "http://browserplus.yahoo.com",
// An array of "secondary" distribution servers, which will be checked
// in order for services if the primary server has no components
// available which match an issued require statement.
"SecondaryDistServers": [
"http://first.fictional.server",
"http://second.fictional.server"
],
// Logging Setup
"Logging" :
{
// Log level. Values: "debug"|"info"|"warn"|"error"|"fatal"|"off"
"level": "BP_LOG_LEVEL",
// Destination. Values: "file"|"console"|"win32"
"dest": "BP_LOG_DEST",
// Log message layout. Values: "standard"|"source"|"raw"
"layout": "standard",
// Time format. Values: "utc"|"local"|"msec"
"timeFormat": "utc",
// File size in KB which will trigger a rollover
"fileRolloverKB": 2048,
// Whether to send file logging from each service to a distinct file.
// Values: "combined"|"separate"
"serviceLogMode": "combined"
},
// Daemon setup
// Syntax: "Options": "option1 option2 etc"
// -fg run in foreground, log to console
"Options":"",
// Auto-shutdown daemon if idle for this time. Use 0 for no auto-shutdown.
"MaxIdleSecs": 5,
// At the end of each BrowserPlus session a small web request is made
// to yahoo to indicate that BrowserPlus was used. This report includes
// * information about the browser being used
// * an "installation id", which is a unique token that's generated
// the first time BrowserPlus runs.
//
// By design, there is *no information* in this request that gives
// Yahoo! information about:
// a) the site that the user is visiting (see, "url": false)
// b) who the user is (the installation token cannot be tracked to a
// specific user).
//
// This information is primarily captured to help Yahoo! understand
// adoption and usage of the BrowserPlus platform.
"UsageReporting":
{
"enabled": true,
"url": false,
"id": true
},
// "Breakpoints" is an array of strings holding named breakpoints.
// Platform code checks for specific entries at certain key points, and if
// a matching entry is found here a DebugBreak will be performed.
// For developers with Visual Studio installed, the DebugBreak will cause an
// opportunity to perform just-in-time attachment of an existing or new
// debugger instance.
// The currently-defined breakpoints are listed below:
// runServiceProcess - A DebugBreak is performed in the service
// "harness" just prior to service load.
// ax.FinalConstruct - A DebugBreak is performed at entry to
// FinalConstruct of the ActiveX plugin.
// PluginInit - Very early in the NPAPI plugin initialization.
// A wonderful spot to stop and set more
// breakpoints.
//"Breakpoints": ["runServiceProcess"],
// How often we check for service updates. We guarantee at least this
// much time will pass between checks, though the true time may be
// much more if sites which use browserplus are not visited.
// The time is in seconds.
"ServiceUpdatePollPeriod": 86400
}
我尝试检索“BuildType”<--JSON 对象的第一个元素。
我更改了 parse_config.c 文件来执行此操作...这是代码:
int
main(void)
{
size_t rd;
yajl_val node;
char errbuf[1024];
/* null plug buffers */
fileData[0] = errbuf[0] = 0;
/* read the entire config file */
rd = fread((void *) fileData, 1, sizeof(fileData) - 1, stdin);
/* file read error handling */
if (rd == 0 && !feof(stdin)) {
fprintf(stderr, "error encountered on file read\n");
return 1;
} else if (rd >= sizeof(fileData) - 1) {
fprintf(stderr, "config file too big\n");
return 1;
}
/* we have the whole config file in memory. let's parse it ... */
node = yajl_tree_parse((const char *) fileData, errbuf, sizeof(errbuf));
/* parse error handling */
if (node == NULL) {
fprintf(stderr, "parse_error: ");
if (strlen(errbuf)) fprintf(stderr, " %s", errbuf);
else fprintf(stderr, "unknown error");
fprintf(stderr, "\n");
return 1;
}
/* ... and extract a nested value from the config file */
{
//const char * path[] = { "Logging", "timeFormat", (const char *) 0 };
注意:如果我尝试获取“DistServer”,它工作得很好,但“BuildType”返回 NULL。
const char * path[] = { "BuildType", (const char *) 0 };
//const char * path[] = { "DistServer", (const char *) 0 };
yajl_val v = yajl_tree_get(node, path, yajl_t_string);
if (v) printf("%s: %s\n", path[0], YAJL_GET_STRING(v));
else printf("no such node: %s\n", path[0] );
//if (v) printf("%s/%s: %s\n", path[0], path[1], YAJL_GET_STRING(v));
//else printf("no such node: %s/%s\n", path[0], path[1]);
}
yajl_tree_free(node);
return 0;
}
我正在使用最新的 YAJL 版本:2.0.2。
提前致谢!
编辑:
这是我的命令输出:
./parse_config < ../../example/sample.config
no such node: BuildType
注意,我正在运行的 parse_config 位于 build/example 目录中
我的 gcc 版本是: gcc 版本 4.4.5 (Ubuntu/Linaro 4.4.4-14ubuntu5)
编辑 2 作为记录,这是随 YAJL 附带的示例代码。我故意使用它而不是我自己的代码,以确保问题不仅仅与我的应用程序有关。同时,我通过使用库提供的回调机制解决了这个问题,并使用
yajl_parse()
and
yajl_complete_parse()
但我仍然想知道为什么原始代码不起作用。
I must be doing something wrong... Or this may be a bug in YAJL, but I highly doubt that.
I'm unable to retrieve the first element from a json object. I went back to the YAJL source to test this with the example parse_config.c and it failed as well.
Using the sample.config
/*
* The configuration file for Yahoo! BrowserPlus, included in the YAJL
* tree as a sample configuration file for parsing.
*
* This is the configuration file for BrowserPlus
*/
{
// The type of build this is, which is accessible to JavaScript via
// BrowserPlus.getPlatformInfo();
// Different build types should only differ in signatures accepted
// (BrowserPlus.crt) and configured distribution servers.
"BuildType": "ephemeral",
// the base url for the "primary" distribution server. This server will
// be the single source of truth for Permissions, and will used to
// attain services
"DistServer": "http://browserplus.yahoo.com",
// An array of "secondary" distribution servers, which will be checked
// in order for services if the primary server has no components
// available which match an issued require statement.
"SecondaryDistServers": [
"http://first.fictional.server",
"http://second.fictional.server"
],
// Logging Setup
"Logging" :
{
// Log level. Values: "debug"|"info"|"warn"|"error"|"fatal"|"off"
"level": "BP_LOG_LEVEL",
// Destination. Values: "file"|"console"|"win32"
"dest": "BP_LOG_DEST",
// Log message layout. Values: "standard"|"source"|"raw"
"layout": "standard",
// Time format. Values: "utc"|"local"|"msec"
"timeFormat": "utc",
// File size in KB which will trigger a rollover
"fileRolloverKB": 2048,
// Whether to send file logging from each service to a distinct file.
// Values: "combined"|"separate"
"serviceLogMode": "combined"
},
// Daemon setup
// Syntax: "Options": "option1 option2 etc"
// -fg run in foreground, log to console
"Options":"",
// Auto-shutdown daemon if idle for this time. Use 0 for no auto-shutdown.
"MaxIdleSecs": 5,
// At the end of each BrowserPlus session a small web request is made
// to yahoo to indicate that BrowserPlus was used. This report includes
// * information about the browser being used
// * an "installation id", which is a unique token that's generated
// the first time BrowserPlus runs.
//
// By design, there is *no information* in this request that gives
// Yahoo! information about:
// a) the site that the user is visiting (see, "url": false)
// b) who the user is (the installation token cannot be tracked to a
// specific user).
//
// This information is primarily captured to help Yahoo! understand
// adoption and usage of the BrowserPlus platform.
"UsageReporting":
{
"enabled": true,
"url": false,
"id": true
},
// "Breakpoints" is an array of strings holding named breakpoints.
// Platform code checks for specific entries at certain key points, and if
// a matching entry is found here a DebugBreak will be performed.
// For developers with Visual Studio installed, the DebugBreak will cause an
// opportunity to perform just-in-time attachment of an existing or new
// debugger instance.
// The currently-defined breakpoints are listed below:
// runServiceProcess - A DebugBreak is performed in the service
// "harness" just prior to service load.
// ax.FinalConstruct - A DebugBreak is performed at entry to
// FinalConstruct of the ActiveX plugin.
// PluginInit - Very early in the NPAPI plugin initialization.
// A wonderful spot to stop and set more
// breakpoints.
//"Breakpoints": ["runServiceProcess"],
// How often we check for service updates. We guarantee at least this
// much time will pass between checks, though the true time may be
// much more if sites which use browserplus are not visited.
// The time is in seconds.
"ServiceUpdatePollPeriod": 86400
}
I try and retrieve the "BuildType" <-- the first element of the JSON object.
I changed the parse_config.c file to do this... here's the code:
int
main(void)
{
size_t rd;
yajl_val node;
char errbuf[1024];
/* null plug buffers */
fileData[0] = errbuf[0] = 0;
/* read the entire config file */
rd = fread((void *) fileData, 1, sizeof(fileData) - 1, stdin);
/* file read error handling */
if (rd == 0 && !feof(stdin)) {
fprintf(stderr, "error encountered on file read\n");
return 1;
} else if (rd >= sizeof(fileData) - 1) {
fprintf(stderr, "config file too big\n");
return 1;
}
/* we have the whole config file in memory. let's parse it ... */
node = yajl_tree_parse((const char *) fileData, errbuf, sizeof(errbuf));
/* parse error handling */
if (node == NULL) {
fprintf(stderr, "parse_error: ");
if (strlen(errbuf)) fprintf(stderr, " %s", errbuf);
else fprintf(stderr, "unknown error");
fprintf(stderr, "\n");
return 1;
}
/* ... and extract a nested value from the config file */
{
//const char * path[] = { "Logging", "timeFormat", (const char *) 0 };
Note: If I try to get "DistServer" it works just fine, but "BuildType" returns NULL.
const char * path[] = { "BuildType", (const char *) 0 };
//const char * path[] = { "DistServer", (const char *) 0 };
yajl_val v = yajl_tree_get(node, path, yajl_t_string);
if (v) printf("%s: %s\n", path[0], YAJL_GET_STRING(v));
else printf("no such node: %s\n", path[0] );
//if (v) printf("%s/%s: %s\n", path[0], path[1], YAJL_GET_STRING(v));
//else printf("no such node: %s/%s\n", path[0], path[1]);
}
yajl_tree_free(node);
return 0;
}
I'm using the latest YAJL version: 2.0.2.
Thanks in advance!
EDIT:
Here's my command output:
./parse_config < ../../example/sample.config
no such node: BuildType
Note, the parse_config that I'm running is in the one in the build/example directory
My gcc version is:
gcc version 4.4.5 (Ubuntu/Linaro 4.4.4-14ubuntu5)
EDIT 2
For the record, this is the sample code that comes with This code came with YAJL. I purposely used it instead of my own code to make sure that the problem wasn't only related to my application. Meanwhile I've worked around the problem by using the callback mechanism the library provides and using
yajl_parse()
and
yajl_complete_parse()
But I still would like to know why the original code wasn't working.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我刚刚使用 2.0.2 版本遇到了同样的错误。这似乎是 yajl 中的一个错误,并已在 github 中修复(“验证 yajl_tree_get 中正确对象的长度”,提交 9c2948a33165c650122d131f31140c15321908f5)。
我已经应用了这个补丁,现在我可以很好地阅读第一个项目了。
I just hit this same bug, using version 2.0.2. It appears to be a bug in yajl and has been fixed in github ("validate the length of the correct object in yajl_tree_get", commit 9c2948a33165c650122d131f31140c15321908f5).
I've applied this patch and I'm now able to read the first item fine.
这看起来像是 yajl 中的一个 bug ...
哇,我没想到本来就是这样。
This looks like it's a bug in yajl...
Wow, I didn't think that would have been the case.