json_parse.cpp 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. #include "json_parse.hpp"
  2. #include <yyjson.h>
  3. #include <stdexcept>
  4. #include <string>
  5. namespace smartbotic::db {
  6. namespace {
  7. nlohmann::json convert(yyjson_val* v) {
  8. if (!v) {
  9. return nullptr;
  10. }
  11. switch (yyjson_get_type(v)) {
  12. case YYJSON_TYPE_NULL:
  13. return nullptr;
  14. case YYJSON_TYPE_BOOL:
  15. return yyjson_get_bool(v);
  16. case YYJSON_TYPE_NUM:
  17. switch (yyjson_get_subtype(v)) {
  18. case YYJSON_SUBTYPE_UINT:
  19. return yyjson_get_uint(v);
  20. case YYJSON_SUBTYPE_SINT:
  21. return yyjson_get_sint(v);
  22. case YYJSON_SUBTYPE_REAL:
  23. default:
  24. return yyjson_get_real(v);
  25. }
  26. case YYJSON_TYPE_STR:
  27. return std::string(yyjson_get_str(v), yyjson_get_len(v));
  28. case YYJSON_TYPE_ARR: {
  29. nlohmann::json out = nlohmann::json::array();
  30. size_t idx, max;
  31. yyjson_val* elem;
  32. yyjson_arr_foreach(v, idx, max, elem) {
  33. out.push_back(convert(elem));
  34. }
  35. return out;
  36. }
  37. case YYJSON_TYPE_OBJ: {
  38. nlohmann::json out = nlohmann::json::object();
  39. size_t idx, max;
  40. yyjson_val* key;
  41. yyjson_val* val;
  42. yyjson_obj_foreach(v, idx, max, key, val) {
  43. out[std::string(yyjson_get_str(key), yyjson_get_len(key))] = convert(val);
  44. }
  45. return out;
  46. }
  47. default:
  48. return nullptr;
  49. }
  50. }
  51. } // namespace
  52. nlohmann::json parse_to_nlohmann(const char* data, size_t length) {
  53. // Null guard only. Empty buffers (length == 0) deliberately fall through
  54. // to yyjson, which returns a positional "empty content" error — keeping
  55. // the parse_error message shape consistent with non-empty malformed
  56. // inputs across all 17 callsites.
  57. if (!data) {
  58. throw nlohmann::json::parse_error::create(
  59. 101, 0, "null input buffer", nullptr);
  60. }
  61. yyjson_read_err err{};
  62. yyjson_doc* doc = yyjson_read_opts(
  63. const_cast<char*>(data), length,
  64. YYJSON_READ_NOFLAG, nullptr, &err);
  65. if (!doc) {
  66. std::string msg = "yyjson parse error: ";
  67. msg += err.msg ? err.msg : "unknown";
  68. throw nlohmann::json::parse_error::create(
  69. 101, static_cast<size_t>(err.pos), msg, nullptr);
  70. }
  71. try {
  72. nlohmann::json out = convert(yyjson_doc_get_root(doc));
  73. yyjson_doc_free(doc);
  74. return out;
  75. } catch (...) {
  76. yyjson_doc_free(doc);
  77. throw;
  78. }
  79. }
  80. nlohmann::json parse_to_nlohmann(std::string_view bytes) {
  81. return parse_to_nlohmann(bytes.data(), bytes.size());
  82. }
  83. } // namespace smartbotic::db