12

我需要在嵌入式系统上解析一个小的 JSON 文件(只有 10K RAM/闪存)。JSON是:

{
"data1":[1,2,3,4,5,6,7,8,9],
"data2":[
     [3,4,5,6,1],
     [8,4,5,6,1],
     [10,4,5,3,61],
     [3,4,5,6,1],
     [3,4,5,6,1],
     [3,4,5,6,1] 
]}

jsmn看起来很适合这个要求,但它不像大多数 JSON 解析器,因为它只给你令牌。我试过了,但无法弄清楚。

有人可以分享一个如何用jsmn解析它的例子吗?

4

4 回答 4

25

jsmn 将为您提供一组标记,这些标记引用您从左到右读取的 JSON 中的标记。

在你的情况下:

token[0]: (outer) object, 2 children
token[1]: string token ("data1")
token[2]: array, 9 children
token[3]: primitive token (1)
etc...

进行解析的基本代码是:

int resultCode;
jsmn_parser p;
jsmntok_t tokens[128]; // a number >= total number of tokens

jsmn_init(&p);
resultCode = jsmn_parse(&p, yourJson, tokens, 256);

另一个技巧是获取代币的价值。令牌包含原始字符串上数据的起点和终点。

jsmntok_t key = tokens[1];
unsigned int length = key.end - key.start;
char keyString[length + 1];    
memcpy(keyString, &yourJson[key.start], length);
keyString[length] = '\0';
printf("Key: %s\n", keyString);

有了它,您应该能够弄清楚如何遍历您的数据。

于 2013-02-05T01:20:14.273 回答
4

我对此也很好奇,所以我做了一个小程序来显示令牌数组的结构:

这个程序:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "jsmn.h"


jsmntok_t t[512];
char jsonStr[512*1024];

int main()
{
  size_t pos = 0;
  int    c;
  while ((c = getchar()) != EOF)
  {
    jsonStr[pos] = c;
    ++pos;
    if (pos == sizeof(jsonStr)) break;
  }
  jsonStr[pos] = 0;

  jsmn_parser p;
  jsmn_init(&p);

  int tCount = jsmn_parse(&p, jsonStr, strlen(jsonStr), t, sizeof(t)/sizeof(*t));

  for (int i = 0; i != tCount; ++i)
  {
    jsmntok_t *token = t + i;
    char * type = 0;
    switch (token->type)
    {
      case JSMN_PRIMITIVE:
        type = "PRIMITIVE";
        break;
      case JSMN_OBJECT:
        type = "OBJECT";
        break;
      case JSMN_ARRAY:
        type = "ARRAY";
        break;
      case JSMN_STRING:
        type = "STRING";
        break;
      default:
        type = "UNDEF";
    }
#ifdef JSMN_PARENT_LINKS
    printf("node: %4d, %9s, parent: %4d, children: %5d, data:\n%.*s, \n", i, type, token->parent, token->size, token->end-token->start, jsonStr+token->start);
#else
    printf("node: %4d, %9s, children: %5d, data:\n%.*s, \n", i, type, token->size, token->end-token->start, jsonStr+token->start);
#endif
  }
}

打印此 json(取自:https ://en.wikipedia.org/wiki/JSON ):

{
  "firstName": "John",
  "lastName": "Smith",
  "isAlive": true,
  "age": 25,
  "address": {
    "streetAddress": "21 2nd Street",
    "city": "New York",
    "state": "NY",
    "postalCode": "10021-3100"
  },
  "phoneNumbers": [
    {
      "type": "home",
      "number": "212 555-1234"
    },
    {
      "type": "office",
      "number": "646 555-4567"
    },
    {
      "type": "mobile",
      "number": "123 456-7890"
    }
  ],
  "children": [],
  "spouse": null
}

作为:

node:    0,    OBJECT, parent:   -1, children:     8, data:
{
  "firstName": "John",
  "lastName": "Smith",
  "isAlive": true,
  "age": 25,
  "address": {
    "streetAddress": "21 2nd Street",
    "city": "New York",
    "state": "NY",
    "postalCode": "10021-3100"
  },
  "phoneNumbers": [
    {
      "type": "home",
      "number": "212 555-1234"
    },
    {
      "type": "office",
      "number": "646 555-4567"
    },
    {
      "type": "mobile",
      "number": "123 456-7890"
    }
  ],
  "children": [],
  "spouse": null
},
node:    1,    STRING, parent:    0, children:     1, data:
firstName,
node:    2,    STRING, parent:    1, children:     0, data:
John,
node:    3,    STRING, parent:    0, children:     1, data:
lastName,
node:    4,    STRING, parent:    3, children:     0, data:
Smith,
node:    5,    STRING, parent:    0, children:     1, data:
isAlive,
node:    6, PRIMITIVE, parent:    5, children:     0, data:
true,
node:    7,    STRING, parent:    0, children:     1, data:
age,
node:    8, PRIMITIVE, parent:    7, children:     0, data:
25,
node:    9,    STRING, parent:    0, children:     1, data:
address,
node:   10,    OBJECT, parent:    9, children:     4, data:
{
    "streetAddress": "21 2nd Street",
    "city": "New York",
    "state": "NY",
    "postalCode": "10021-3100"
  },
node:   11,    STRING, parent:   10, children:     1, data:
streetAddress,
node:   12,    STRING, parent:   11, children:     0, data:
21 2nd Street,
node:   13,    STRING, parent:   10, children:     1, data:
city,
node:   14,    STRING, parent:   13, children:     0, data:
New York,
node:   15,    STRING, parent:   10, children:     1, data:
state,
node:   16,    STRING, parent:   15, children:     0, data:
NY,
node:   17,    STRING, parent:   10, children:     1, data:
postalCode,
node:   18,    STRING, parent:   17, children:     0, data:
10021-3100,
node:   19,    STRING, parent:    0, children:     1, data:
phoneNumbers,
node:   20,     ARRAY, parent:   19, children:     3, data:
[
    {
      "type": "home",
      "number": "212 555-1234"
    },
    {
      "type": "office",
      "number": "646 555-4567"
    },
    {
      "type": "mobile",
      "number": "123 456-7890"
    }
  ],
node:   21,    OBJECT, parent:   20, children:     2, data:
{
      "type": "home",
      "number": "212 555-1234"
    },
node:   22,    STRING, parent:   21, children:     1, data:
type,
node:   23,    STRING, parent:   22, children:     0, data:
home,
node:   24,    STRING, parent:   21, children:     1, data:
number,
node:   25,    STRING, parent:   24, children:     0, data:
212 555-1234,
node:   26,    OBJECT, parent:   20, children:     2, data:
{
      "type": "office",
      "number": "646 555-4567"
    },
node:   27,    STRING, parent:   26, children:     1, data:
type,
node:   28,    STRING, parent:   27, children:     0, data:
office,
node:   29,    STRING, parent:   26, children:     1, data:
number,
node:   30,    STRING, parent:   29, children:     0, data:
646 555-4567,
node:   31,    OBJECT, parent:   20, children:     2, data:
{
      "type": "mobile",
      "number": "123 456-7890"
    },
node:   32,    STRING, parent:   31, children:     1, data:
type,
node:   33,    STRING, parent:   32, children:     0, data:
mobile,
node:   34,    STRING, parent:   31, children:     1, data:
number,
node:   35,    STRING, parent:   34, children:     0, data:
123 456-7890,
node:   36,    STRING, parent:    0, children:     1, data:
children,
node:   37,     ARRAY, parent:   36, children:     0, data:
[],
node:   38,    STRING, parent:    0, children:     1, data:
spouse,
node:   39, PRIMITIVE, parent:   38, children:     0, data:
null,
于 2017-08-10T06:17:14.490 回答
0

您可以使用tiny-json。它给你的不仅仅是代币。我用过 16 位和 32 位的微控制器,它工作正常。

char str[] = "{"
                 "\"data1\":[1,2,3,4,5,6,7,8,9],"
                 "\"data2\":["
                     "[3,4,5,6,1],"
                     "[8,4,5,6,1],"
                     "[10,4,5,3,61],"
                     "[3,4,5,6,1],"
                     "[3,4,5,6,1],"
                     "[3,4,5,6,1]"
                 "]"
             "}";
puts( str );

json_t pool[64];
json_t const* root = json_create( str, pool, 64 );

json_t const* data1 = json_getProperty( root, "data1" );
if ( data1 && JSON_ARRAY == json_getType( data1 ) ) {

    json_t const* field = json_getChild( data1 );
    while( field ) {

        if ( JSON_INTEGER == json_getType( field ) ) {
            long long int data = json_getInteger( field );
            printf("Integer from data1: %lld\n", data );
        }

        field = json_getSibling( field );
    }
}

json_t const* data2 = json_getProperty( root, "data2" );
if ( data2 && JSON_ARRAY == json_getType( data2 ) ) {

    json_t const* array = json_getChild( data2 );
    while( array ) {

        if ( JSON_ARRAY == json_getType( array ) ) {
            puts("Array in data2");

            json_t const* field = json_getChild( array );
            while( field ) {

                if ( JSON_INTEGER == json_getType( field ) ) {
                    long long int data = json_getInteger( field );
                    printf("Integer from array of data2: %lld\n", data );
                }

                field = json_getSibling( field ); 
            }
        }
        array = json_getSibling( array );
    }
} 
于 2017-04-04T12:44:50.567 回答
0

我刚刚创建了 jsmnRipper。这段代码让你以一种非常简单的方式提取用 jsmn 解析的标记。

这里以 ACRCloud 返回的 JSON 消息的解析结果为例

  • metadata.music[1].score:100:
  • metadata.music[1].album.name:Depeche Mode 最佳卷 1:
  • metadata.music[1].artists[0].name:Depeche 模式:
  • metadata.music[1].title:Enjoy The Silence (Remastered Version) (Original):

您可以在https://github.com/ipserc/jsmnRipper找到执行此操作的代码

于 2018-05-27T18:31:38.907 回答