jsonx.cpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. // JSON to JSONx conversion example, using SAX API.
  2. // JSONx is an IBM standard format to represent JSON as XML.
  3. // https://www-01.ibm.com/support/knowledgecenter/SS9H2Y_7.1.0/com.ibm.dp.doc/json_jsonx.html
  4. // This example parses JSON text from stdin with validation,
  5. // and convert to JSONx format to stdout.
  6. // Need compile with -D__STDC_FORMAT_MACROS for defining PRId64 and PRIu64 macros.
  7. #include <rtthread.h>
  8. #include "rapidjson/reader.h"
  9. #include "rapidjson/stringbuffer.h"
  10. #include "rapidjson/filereadstream.h"
  11. #include "rapidjson/filewritestream.h"
  12. #include "rapidjson/error/en.h"
  13. #include <cstdio>
  14. using namespace rapidjson;
  15. // For simplicity, this example only read/write in UTF-8 encoding
  16. template <typename OutputStream>
  17. class JsonxWriter {
  18. public:
  19. JsonxWriter(OutputStream& os) : os_(os), name_(), level_(0), hasName_(false) {
  20. }
  21. bool Null() {
  22. return WriteStartElement("null", true);
  23. }
  24. bool Bool(bool b) {
  25. return
  26. WriteStartElement("boolean") &&
  27. WriteString(b ? "true" : "false") &&
  28. WriteEndElement("boolean");
  29. }
  30. bool Int(int i) {
  31. char buffer[12];
  32. return WriteNumberElement(buffer, sprintf(buffer, "%d", i));
  33. }
  34. bool Uint(unsigned i) {
  35. char buffer[11];
  36. return WriteNumberElement(buffer, sprintf(buffer, "%u", i));
  37. }
  38. bool Int64(int64_t i) {
  39. char buffer[21];
  40. return WriteNumberElement(buffer, sprintf(buffer, "%" PRId64, i));
  41. }
  42. bool Uint64(uint64_t i) {
  43. char buffer[21];
  44. return WriteNumberElement(buffer, sprintf(buffer, "%" PRIu64, i));
  45. }
  46. bool Double(double d) {
  47. char buffer[30];
  48. return WriteNumberElement(buffer, sprintf(buffer, "%.17g", d));
  49. }
  50. bool RawNumber(const char* str, SizeType length, bool) {
  51. return
  52. WriteStartElement("number") &&
  53. WriteEscapedText(str, length) &&
  54. WriteEndElement("number");
  55. }
  56. bool String(const char* str, SizeType length, bool) {
  57. return
  58. WriteStartElement("string") &&
  59. WriteEscapedText(str, length) &&
  60. WriteEndElement("string");
  61. }
  62. bool StartObject() {
  63. return WriteStartElement("object");
  64. }
  65. bool Key(const char* str, SizeType length, bool) {
  66. // backup key to name_
  67. name_.Clear();
  68. for (SizeType i = 0; i < length; i++)
  69. name_.Put(str[i]);
  70. hasName_ = true;
  71. return true;
  72. }
  73. bool EndObject(SizeType) {
  74. return WriteEndElement("object");
  75. }
  76. bool StartArray() {
  77. return WriteStartElement("array");
  78. }
  79. bool EndArray(SizeType) {
  80. return WriteEndElement("array");
  81. }
  82. private:
  83. bool WriteString(const char* s) {
  84. while (*s)
  85. os_.Put(*s++);
  86. return true;
  87. }
  88. bool WriteEscapedAttributeValue(const char* s, size_t length) {
  89. for (size_t i = 0; i < length; i++) {
  90. switch (s[i]) {
  91. case '&': WriteString("&amp;"); break;
  92. case '<': WriteString("&lt;"); break;
  93. case '"': WriteString("&quot;"); break;
  94. default: os_.Put(s[i]); break;
  95. }
  96. }
  97. return true;
  98. }
  99. bool WriteEscapedText(const char* s, size_t length) {
  100. for (size_t i = 0; i < length; i++) {
  101. switch (s[i]) {
  102. case '&': WriteString("&amp;"); break;
  103. case '<': WriteString("&lt;"); break;
  104. default: os_.Put(s[i]); break;
  105. }
  106. }
  107. return true;
  108. }
  109. bool WriteStartElement(const char* type, bool emptyElement = false) {
  110. if (level_ == 0)
  111. if (!WriteString("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"))
  112. return false;
  113. if (!WriteString("<json:") || !WriteString(type))
  114. return false;
  115. // For root element, need to add declarations
  116. if (level_ == 0) {
  117. if (!WriteString(
  118. " xsi:schemaLocation=\"http://www.datapower.com/schemas/json jsonx.xsd\""
  119. " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
  120. " xmlns:json=\"http://www.ibm.com/xmlns/prod/2009/jsonx\""))
  121. return false;
  122. }
  123. if (hasName_) {
  124. hasName_ = false;
  125. if (!WriteString(" name=\"") ||
  126. !WriteEscapedAttributeValue(name_.GetString(), name_.GetSize()) ||
  127. !WriteString("\""))
  128. return false;
  129. }
  130. if (emptyElement)
  131. return WriteString("/>");
  132. else {
  133. level_++;
  134. return WriteString(">");
  135. }
  136. }
  137. bool WriteEndElement(const char* type) {
  138. if (!WriteString("</json:") ||
  139. !WriteString(type) ||
  140. !WriteString(">"))
  141. return false;
  142. // For the last end tag, flush the output stream.
  143. if (--level_ == 0)
  144. os_.Flush();
  145. return true;
  146. }
  147. bool WriteNumberElement(const char* buffer, int length) {
  148. if (!WriteStartElement("number"))
  149. return false;
  150. for (int j = 0; j < length; j++)
  151. os_.Put(buffer[j]);
  152. return WriteEndElement("number");
  153. }
  154. OutputStream& os_;
  155. StringBuffer name_;
  156. unsigned level_;
  157. bool hasName_;
  158. };
  159. int jsonx(int, char*[]) {
  160. // Prepare JSON reader and input stream.
  161. Reader reader;
  162. char readBuffer[1024];
  163. FileReadStream is(stdin, readBuffer, sizeof(readBuffer));
  164. // Prepare JSON writer and output stream.
  165. char writeBuffer[1024];
  166. FileWriteStream os(stdout, writeBuffer, sizeof(writeBuffer));
  167. JsonxWriter<FileWriteStream> writer(os);
  168. // JSON reader parse from the input stream and let writer generate the output.
  169. if (!reader.Parse(is, writer)) {
  170. fprintf(stderr, "\nError(%u): %s\n", static_cast<unsigned>(reader.GetErrorOffset()), GetParseError_En(reader.GetParseErrorCode()));
  171. return 1;
  172. }
  173. return 0;
  174. }
  175. MSH_CMD_EXPORT(jsonx, rapid json look jsonx example);