jsonx.cpp 5.9 KB

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