RapidJSON Преобразует строковое значение в индексированный массив?

У меня есть строка JSON, в которой значение на самом деле является строкой, но мне нужно получить к ней доступ, как к массиву JSON. {"data" : "[A,B,C]"}.

Есть ли способ проанализировать VALUE как индексированный массив с помощью RapidJSON, чтобы я получил такой документ, как: {"0" : "A", "1" : "B", "2" : "C"}


person devilzk83    schedule 06.06.2016    source источник


Ответы (1)


RapidJSON должен полностью соответствовать RFC7159/ECMA-404.

Нет, никак, нужно делать это вручную.

Например, используя регулярное выражение:

#include <iostream>
#include <iterator>
#include <string>
#include <regex>

static std::regex value_regex("[\\s]*([\\w\\s]+),?", std::regex::optimize);

std::string parse(const std::string& value) {
    if (value.at(0) != '[' || value.at(value.size() - 1) != ']') {
        throw std::invalid_argument("Error in Parse [must start with '[' and end with ']']: " + value);
    }

    std::string result("{");
    std::sregex_iterator next(++value.begin(), --value.end(), value_regex, std::regex_constants::match_continuous);
    std::sregex_iterator end;
    size_t len = 0, cont = 0;
    while (next != end) {
        if (cont) {
            result.append(", \"").append(std::to_string(cont)).append("\":\"").append(next->str(1)).append(1, '\"');
        } else {
            result.append(1, '\"').append(std::to_string(cont)).append("\":\"").append(next->str(1)).append(1, '\"');
        }
        len += next->length(0);
        ++next;
        ++cont;
    }

    if (len != value.size() - 2) {
        throw std::invalid_argument("Error in Parse [" + std::to_string(len) + "]: " + value);
    }

    result.append(1, '}');
    return result;
}

int main() {
    // Tests
    try {
        std::string value("[A,B,C,D,E]");
        std::cout << value << "  ->  " << parse(value) << std::endl;
    } catch (const std::invalid_argument& err) {
        std::cout << err.what() << std::endl;
    }
    try {
        std::string value("[  A, B X, Z]");
        std::cout << value << "  ->  " << parse(value) << std::endl;
    } catch (const std::invalid_argument& err) {
        std::cout << err.what() << std::endl;
    }
    try {
        std::string value("[A,BaaayyX, Z]");
        std::cout << value << "  ->  " << parse(value) << std::endl;
    } catch (const std::invalid_argument& err) {
        std::cout << err.what() << std::endl;
    }
    try {
        std::string value("[A,B,C,]");
        std::cout << value << "  ->  " << parse(value) << std::endl;
    } catch (const std::invalid_argument& err) {
        std::cout << err.what() << std::endl;
    }
    try {
        std::string value("[]");
        std::cout << value << "  ->  " << parse(value) << std::endl;
    } catch (const std::invalid_argument& err) {
        std::cout << err.what() << std::endl;
    }


    // Errors
    try {
        std::string value("A,B,C");
        std::cout << value << "  ->  " << parse(value) << std::endl;
    } catch (const std::invalid_argument& err) {
        std::cout << err.what() << std::endl;
    }

    try {
        std::string value("A,B,C]");
        std::cout << value << "  ->  " << parse(value) << std::endl;
    } catch (const std::invalid_argument& err) {
        std::cout << err.what() << std::endl;
    }

    try {
        std::string value("[A,B,C");
        std::cout << value << "  ->  " << parse(value) << std::endl;
    } catch (const std::invalid_argument& err) {
        std::cout << err.what() << std::endl;
    }

    try {
        std::string value("[,A,B,C]");
        std::cout << value << "  ->  " << parse(value) << std::endl;
    } catch (const std::invalid_argument& err) {
        std::cout << err.what() << std::endl;
    }

    try {
        std::string value("");
        std::cout << value << "  ->  " << parse(value) << std::endl;
    } catch (const std::exception& err) {
        std::cout << err.what() << std::endl;
    }

    try {
        std::string value("[");
        std::cout << value << "  ->  " << parse(value) << std::endl;
    } catch (const std::exception& err) {
        std::cout << err.what() << std::endl;
    }

    try {
        std::string value("]");
        std::cout << value << "  ->  " << parse(value) << std::endl;
    } catch (const std::exception& err) {
        std::cout << err.what() << std::endl;
    }
}

Выход:

[A,B,C,D,E]  ->  {"0":"A", "1":"B", "2":"C", "3":"D", "4":"E"}
[  A, B X, Z]  ->  {"0":"A", "1":"B X", "2":"Z"}
[A,BaaayyX, Z]  ->  {"0":"A", "1":"BaaayyX", "2":"Z"}
[A,B,C,]  ->  {"0":"A", "1":"B", "2":"C"}
[]  ->  {}
A,B,C  ->  Error in Parse [must start with '[' and end with ']']: A,B,C
A,B,C]  ->  Error in Parse [must start with '[' and end with ']']: A,B,C]
[A,B,C  ->  Error in Parse [must start with '[' and end with ']']: [A,B,C
[,A,B,C]  ->  Error in Parse [0]: [,A,B,C]
  ->  basic_string
[  ->  Error in Parse [must start with '[' and end with ']']: [
]  ->  Error in Parse [must start with '[' and end with ']']: ]

Вы можете настроить регулярное выражение, чтобы оно стало более гибким или более строгим.

person chema989    schedule 06.06.2016
comment
Спасибо за ответ. Я попробую этот подход. Ранее я использовал библиотеку разбора JSON на C# (для проекта Unity), которая позволяла анализировать JSON таким образом. Но я понял суть RFC и поэтому выберу это индивидуальное решение. - person devilzk83; 07.06.2016