jcat是一个shell下的解析json的工具,具有以下功能:

    1. 支持指定路径解析,打印指定路径下的所有对象信息
    2. 支持宏路径,可以级联宏替换
    3. 使用tbox进行了跨平台支持,预编译版本直接可以在./tbox/tool目录下找到,因为新版tbox makefile架构就是采用jcat来解析*.pkg/manifest.json清单文件

    使用方式拿polarssl.pkg/manifest.json的举例:

    1. {
    2. "format":
    3. {
    4. "name": "The TBOOX Package Format"
    5. , "version": "v1.0.1"
    6. , "website": "http://www.tboox.org"
    7. }
    8.  
    9. , "package":
    10. {
    11. "name": "The PolarSSL Library"
    12. , "website": "http://www.polarssl.org"
    13. }
    14.  
    15. , "compiler":
    16. {
    17. "default":
    18. {
    19. "debug":
    20. {
    21. "libs": "polarssl"
    22. , "libpath": ""
    23. , "incpath": ""
    24. , "libflags": ""
    25. , "incflags": ""
    26. }
    27. , "release": "$.compiler.default.debug"
    28. }
    29.  
    30. , "linux" :
    31. {
    32. "x64": "$.compiler.default"
    33. }
    34.  
    35. , "mac" :
    36. {
    37. "x86": "$.compiler.default"
    38. , "x64": "$.compiler.default"
    39. }
    40.  
    41. , "msvc" :
    42. {
    43. "x86": "$.compiler.default"
    44. }
    45.  
    46. , "mingw" :
    47. {
    48. "x86": "$.compiler.default"
    49. }
    50.  
    51. , "cygwin" :
    52. {
    53. "x86": "$.compiler.default"
    54. }
    55.  
    56. , "ios" :
    57. {
    58. "armv7": "$.compiler.default"
    59. , "armv7s": "$.compiler.default"
    60. , "arm64": "$.compiler.default"
    61. }
    62.  
    63. , "android" :
    64. {
    65. "armv5te": "$.compiler.default"
    66. , "armv6": "$.compiler.default"
    67. }
    68. }
    69. }

    上述manifest.json中,以$开头的字符串均为宏路径,例如:$.compiler.default,用来引用其他地方的配置数据,减小配置冗余

    执行jcat, 获取 .compiler.mac.x64.debug 路径的内容

    1. ./tool/jcat/jcat --filter=.compiler.mac.x64.debug ./pkg/polarssl.pkg/manifest.json

    返回结果如下:

    1. {"incpath":"","incflags":"","libs":"polarssl","libflags":"","libpath":""}

    是不是很方便?解析过程可以递归处理替换宏路径,返回真实的数据。其他详细使用方式,可以通过如下命令获取:

    1. ./tool/jcat/jcat --help

    看了使用过程,是不是觉得实现这样一个jcat很复杂呢,其实非常简单,只要使用TBOX的object库,可以非常方便的实现它,下面就晒下jcat的代码吧:

    1. #include "tbox/tbox.h"
    2.  
    3. static tb_option_item_t g_options[] =
    4. {
    5. { 'f'
    6. , "filter"
    7. , TB_OPTION_MODE_KEY_VAL
    8. , TB_OPTION_TYPE_CSTR
    9. , "the json filter\n"
    10. ".e.g\n"
    11. "\n"
    12. "file:\n"
    13. "{\n"
    14. " \"string\": \"hello world!\"\n"
    15. ", \"com.xxx.xxx\": \"hello world\"\n"
    16. ", \"integer\": 31415926\n"
    17. ", \"array\":\n"
    18. " [\n"
    19. " \"hello world!\"\n"
    20. " , 31415926\n"
    21. " , 3.1415926\n"
    22. " , false\n"
    23. " , true\n"
    24. " , { \"string\": \"hello world!\" }\n"
    25. " ]\n"
    26. ", \"macro\": \"$.array[2]\"\n"
    27. ", \"macro2\": \"$.com\\\\.xxx\\\\.xxx\"\n"
    28. ", \"macro3\": \"$.macro\"\n"
    29. ", \"macro4\": \"$.array\"\n"
    30. "}\n"
    31. "\n"
    32. "filter:\n"
    33. " 1. \".string\" : hello world!\n"
    34. " 2. \".array[1]\" : 31415926\n"
    35. " 3. \".array[5].string\" : hello world!\n"
    36. " 4. \".com\\.xxx\\.xxx\" : hello world\n"
    37. " 5. \".macro\" : 3.1415926\n"
    38. " 6. \".macro2\" : hello world\n"
    39. " 7. \".macro3\" : 3.1415926\n"
    40. " 8. \".macro4[0]\" : \"hello world!\"\n"
    41. }
    42. , {'h', "help", TB_OPTION_MODE_KEY, TB_OPTION_TYPE_BOOL, "display this help and exit"}
    43. , {'-', "file", TB_OPTION_MODE_VAL, TB_OPTION_TYPE_CSTR, "the json file" }
    44.  
    45. };
    46.  
    47. /* //////////////////////////////////////////////////////////////////////////////////////
    48. * main
    49. */
    50. tb_int_t main(tb_int_t argc, tb_char_t** argv)
    51. {
    52. // init tbox
    53. if (!tb_init(tb_null, tb_null, 0)) return 0;
    54.  
    55. // init option
    56. tb_option_ref_t option = tb_option_init("jcat", "cat the json file", g_options);
    57. if (option)
    58. {
    59. // done option
    60. if (tb_option_done(option, argc - 1, &argv[1]))
    61. {
    62. // done file
    63. if (tb_option_find(option, "file"))
    64. {
    65. // load object
    66. tb_object_ref_t root = tb_object_read_from_url(tb_option_item_cstr(option, "file"));
    67. if (root)
    68. {
    69. // done filter
    70. tb_object_ref_t object = root;
    71. if (tb_option_find(option, "filter"))
    72. object = tb_object_seek(root, tb_option_item_cstr(option, "filter"), tb_true);
    73.  
    74. // dump 数据对象,这里主要为了过滤 字符串内容的 ""
    75. // 否则直接使用tb_object_dump会更简单,只需一行代码
    76. if (object)
    77. {
    78. // done
    79. tb_char_t info[8192] = {0};
    80. tb_long_t size = tb_object_writ_to_data(object, (tb_byte_t*)info, sizeof(info), TB_OBJECT_FORMAT_JSON | TB_OBJECT_FORMAT_DEFLATE);
    81. if (size > 0)
    82. {
    83. // strip string: ""
    84. tb_char_t* show = info;
    85. if (info[0] == '\"' && info[size - 1] == '\"')
    86. {
    87. show++;
    88. info[size - 1] = '\0';
    89. }
    90.  
    91. // trace
    92. tb_printf("%s\n", show);
    93. }
    94. }
    95.  
    96. // exit object
    97. tb_object_exit(root);
    98. }
    99. }
    100. else tb_option_help(option);
    101. }
    102. else tb_option_help(option);
    103.  
    104. // exit option
    105. tb_option_exit(option);
    106. }
    107.  
    108. // exit tbox
    109. tb_exit();
    110.  
    111. // ok
    112. return 0;
    113. }

    简单吧,就只要一百行代码,还支持详细的命令行选项支持。

    附带一句:其实jcat同时还可以支持解析xml和plist哦,因为他用了object模块的多数据格式探测功能,完全可以自动解析不同格式的数据,还能方便扩展自己的数据格式。