208 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			208 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // JSON to JSONx conversion exmaple, using SAX API.
 | |
| // JSONx is an IBM standard format to represent JSON as XML.
 | |
| // https://www-01.ibm.com/support/knowledgecenter/SS9H2Y_7.1.0/com.ibm.dp.doc/json_jsonx.html
 | |
| // This example parses JSON text from stdin with validation, 
 | |
| // and convert to JSONx format to stdout.
 | |
| // Need compile with -D__STDC_FORMAT_MACROS for defining PRId64 and PRIu64 macros.
 | |
| 
 | |
| #include "rapidjson/reader.h"
 | |
| #include "rapidjson/stringbuffer.h"
 | |
| #include "rapidjson/filereadstream.h"
 | |
| #include "rapidjson/filewritestream.h"
 | |
| #include "rapidjson/error/en.h"
 | |
| #include <cstdio>
 | |
| 
 | |
| using namespace rapidjson;
 | |
| 
 | |
| // For simplicity, this example only read/write in UTF-8 encoding
 | |
| template <typename OutputStream>
 | |
| class JsonxWriter {
 | |
| public:
 | |
|     JsonxWriter(OutputStream& os) : os_(os), name_(), level_(0), hasName_(false) {
 | |
|     }
 | |
| 
 | |
|     bool Null() {
 | |
|         return WriteStartElement("null", true);
 | |
|     }
 | |
|     
 | |
|     bool Bool(bool b) {
 | |
|         return 
 | |
|             WriteStartElement("boolean") &&
 | |
|             WriteString(b ? "true" : "false") &&
 | |
|             WriteEndElement("boolean");
 | |
|     }
 | |
|     
 | |
|     bool Int(int i) {
 | |
|         char buffer[12];
 | |
|         return WriteNumberElement(buffer, sprintf(buffer, "%d", i));
 | |
|     }
 | |
|     
 | |
|     bool Uint(unsigned i) {
 | |
|         char buffer[11];
 | |
|         return WriteNumberElement(buffer, sprintf(buffer, "%u", i));
 | |
|     }
 | |
|     
 | |
|     bool Int64(int64_t i) {
 | |
|         char buffer[21];
 | |
|         return WriteNumberElement(buffer, sprintf(buffer, "%" PRId64, i));
 | |
|     }
 | |
|     
 | |
|     bool Uint64(uint64_t i) {
 | |
|         char buffer[21];
 | |
|         return WriteNumberElement(buffer, sprintf(buffer, "%" PRIu64, i));
 | |
|     }
 | |
|     
 | |
|     bool Double(double d) {
 | |
|         char buffer[30];
 | |
|         return WriteNumberElement(buffer, sprintf(buffer, "%.17g", d));
 | |
|     }
 | |
| 
 | |
|     bool RawNumber(const char* str, SizeType length, bool) {
 | |
|         return
 | |
|             WriteStartElement("number") &&
 | |
|             WriteEscapedText(str, length) &&
 | |
|             WriteEndElement("number");
 | |
|     }
 | |
| 
 | |
|     bool String(const char* str, SizeType length, bool) {
 | |
|         return
 | |
|             WriteStartElement("string") &&
 | |
|             WriteEscapedText(str, length) &&
 | |
|             WriteEndElement("string");
 | |
|     }
 | |
| 
 | |
|     bool StartObject() {
 | |
|         return WriteStartElement("object");
 | |
|     }
 | |
| 
 | |
|     bool Key(const char* str, SizeType length, bool) {
 | |
|         // backup key to name_
 | |
|         name_.Clear();
 | |
|         for (SizeType i = 0; i < length; i++)
 | |
|             name_.Put(str[i]);
 | |
|         hasName_ = true;
 | |
|         return true;
 | |
|     }
 | |
| 
 | |
|     bool EndObject(SizeType) {
 | |
|         return WriteEndElement("object");
 | |
|     }
 | |
| 
 | |
|     bool StartArray() {
 | |
|         return WriteStartElement("array");
 | |
|     }
 | |
| 
 | |
|     bool EndArray(SizeType) {
 | |
|         return WriteEndElement("array");
 | |
|     }
 | |
| 
 | |
| private:
 | |
|     bool WriteString(const char* s) {
 | |
|         while (*s)
 | |
|             os_.Put(*s++);
 | |
|         return true;
 | |
|     }
 | |
| 
 | |
|     bool WriteEscapedAttributeValue(const char* s, size_t length) {
 | |
|         for (size_t i = 0; i < length; i++) {
 | |
|             switch (s[i]) {
 | |
|                 case '&': WriteString("&"); break;
 | |
|                 case '<': WriteString("<"); break;
 | |
|                 case '"': WriteString("""); break;
 | |
|                 default: os_.Put(s[i]); break;
 | |
|             }
 | |
|         }
 | |
|         return true;
 | |
|     }
 | |
| 
 | |
|     bool WriteEscapedText(const char* s, size_t length) {
 | |
|         for (size_t i = 0; i < length; i++) {
 | |
|             switch (s[i]) {
 | |
|                 case '&': WriteString("&"); break;
 | |
|                 case '<': WriteString("<"); break;
 | |
|                 default: os_.Put(s[i]); break;
 | |
|             }
 | |
|         }
 | |
|         return true;
 | |
|     }
 | |
| 
 | |
|     bool WriteStartElement(const char* type, bool emptyElement = false) {
 | |
|         if (level_ == 0)
 | |
|             if (!WriteString("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"))
 | |
|                 return false;
 | |
| 
 | |
|         if (!WriteString("<json:") || !WriteString(type))
 | |
|             return false;
 | |
| 
 | |
|         // For root element, need to add declarations
 | |
|         if (level_ == 0) {
 | |
|             if (!WriteString(
 | |
|                 " xsi:schemaLocation=\"http://www.datapower.com/schemas/json jsonx.xsd\""
 | |
|                 " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
 | |
|                 " xmlns:json=\"http://www.ibm.com/xmlns/prod/2009/jsonx\""))
 | |
|                 return false;
 | |
|         }
 | |
| 
 | |
|         if (hasName_) {
 | |
|             hasName_ = false;
 | |
|             if (!WriteString(" name=\"") ||
 | |
|                 !WriteEscapedAttributeValue(name_.GetString(), name_.GetSize()) ||
 | |
|                 !WriteString("\""))
 | |
|                 return false;
 | |
|         }
 | |
| 
 | |
|         if (emptyElement)
 | |
|             return WriteString("/>");
 | |
|         else {
 | |
|             level_++;
 | |
|             return WriteString(">");
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     bool WriteEndElement(const char* type) {
 | |
|         if (!WriteString("</json:") ||
 | |
|             !WriteString(type) ||
 | |
|             !WriteString(">"))
 | |
|             return false;
 | |
| 
 | |
|         // For the last end tag, flush the output stream.
 | |
|         if (--level_ == 0)
 | |
|             os_.Flush();
 | |
| 
 | |
|         return true;
 | |
|     }
 | |
| 
 | |
|     bool WriteNumberElement(const char* buffer, int length) {
 | |
|         if (!WriteStartElement("number"))
 | |
|             return false;
 | |
|         for (int j = 0; j < length; j++)
 | |
|             os_.Put(buffer[j]);
 | |
|         return WriteEndElement("number");
 | |
|     }
 | |
| 
 | |
|     OutputStream& os_;
 | |
|     StringBuffer name_;
 | |
|     unsigned level_;
 | |
|     bool hasName_;
 | |
| };
 | |
| 
 | |
| int main(int, char*[]) {
 | |
|     // Prepare JSON reader and input stream.
 | |
|     Reader reader;
 | |
|     char readBuffer[65536];
 | |
|     FileReadStream is(stdin, readBuffer, sizeof(readBuffer));
 | |
| 
 | |
|     // Prepare JSON writer and output stream.
 | |
|     char writeBuffer[65536];
 | |
|     FileWriteStream os(stdout, writeBuffer, sizeof(writeBuffer));
 | |
|     JsonxWriter<FileWriteStream> writer(os);
 | |
| 
 | |
|     // JSON reader parse from the input stream and let writer generate the output.
 | |
|     if (!reader.Parse(is, writer)) {
 | |
|         fprintf(stderr, "\nError(%u): %s\n", static_cast<unsigned>(reader.GetErrorOffset()), GetParseError_En(reader.GetParseErrorCode()));
 | |
|         return 1;
 | |
|     }
 | |
| 
 | |
|     return 0;
 | |
| }
 |