Skip to content

JSONPath #821

Open
Open
@cdaller

Description

@cdaller

I have an application that fetches a json file from an http server and extracts a value from the json. The url (and therefore the structure of the json) is configurable during runtime. So I wanted to use a json path to define which value to extract from the json content. I googled, but could not find any, so I wrote a very simple jsonPath parser.

I think a method like this would be quite useful in the library - what do you think?

As I am not very experienced in C++, the method could (and probably should) be rewritten before being integrated :-)

// parse jsonPaths like $.foo[1].bar.baz[2][3].value (equals to foo[1].bar.baz[2][3].value)
float parseJson(char* jsonString, char *jsonPath) {
    float jsonValue;
    DynamicJsonBuffer jsonBuffer;
    
    JsonVariant root = jsonBuffer.parse(jsonString);
    JsonVariant element = root;

    if (root.success()) {
        // parse jsonPath and navigate through json object:
        char pathElement[40];
        int pathIndex = 0;

        printf("parsing '%s'\n", jsonPath);
        for (int i = 0; jsonPath[i] != '\0'; i++){
            if (jsonPath[i] == '$') {
                element = root;
            } else if (jsonPath[i] == '.') {
                if (pathIndex > 0) {
                    pathElement[pathIndex++] = '\0';
                    // printf("pathElement '%s'\n", pathElement);
                    pathIndex = 0;
                    element = element[pathElement];
                    if (!element.success()) {
                        printf("failed to parse key %s\n", pathElement);
                    }
                }
            } else if ((jsonPath[i] >= 'a' && jsonPath[i] <= 'z') 
                    || (jsonPath[i] >= 'A' && jsonPath[i] <= 'Z') 
                    || (jsonPath[i] >= '0' && jsonPath[i] <= '9')
                    || jsonPath[i] == '-' || jsonPath[i] == '_'
                    ) {
                pathElement[pathIndex++] = jsonPath[i];
            } else if (jsonPath[i] == '[') {
                if (pathIndex > 0) {
                    pathElement[pathIndex++] = '\0';
                    // printf("pathElement '%s'\n", pathElement);
                    pathIndex = 0;
                    element = element[pathElement];
                    if (!element.success()) {
                        printf("failed in parsing key %s\n", pathElement);
                    }
                }
            } else if (jsonPath[i] == ']') {
                pathElement[pathIndex++] = '\0';
                int arrayIndex = strtod(pathElement, NULL);
                // printf("index '%s' = %d\n", pathElement, arrayIndex);
                pathIndex = 0;
                element = element[arrayIndex];
                if (!element.success()) {
                    printf("failed in parsing index %d\n", arrayIndex);
                }
            }
        }  
        // final token if any:
        if (pathIndex > 0) {
            pathElement[pathIndex++] = '\0';
            // printf("pathElement '%s'\n", pathElement);
            pathIndex = 0;
            element = element[pathElement];
            if (!element.success()) {
                printf("failed in parsing key %s\n", pathElement);
            }
        }

        jsonValue = element.as<float>();

        //jsonValue = measurements[1]["sensordatavalues"][0]["value"];
        printf("success reading value: %f\n", jsonValue);
    } else {
        jsonValue = -1; // should be NaN or something similar
        printf("could not parse json for value");
    }
    return jsonValue;
}

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions