diff --git a/extensions/windows-event-log/ConsumeWindowsEventLog.cpp b/extensions/windows-event-log/ConsumeWindowsEventLog.cpp index 285cd21f442..e85dd4b3a57 100644 --- a/extensions/windows-event-log/ConsumeWindowsEventLog.cpp +++ b/extensions/windows-event-log/ConsumeWindowsEventLog.cpp @@ -34,7 +34,7 @@ #include "wel/MetadataWalker.h" #include "wel/XMLString.h" #include "wel/UnicodeConversion.h" -#include "wel/JSONConverter.h" +#include "wel/JSONUtils.h" #include "io/BufferStream.h" #include "core/ProcessContext.h" @@ -636,7 +636,7 @@ bool ConsumeWindowsEventLog::createEventRender(EVT_HANDLE hEvent, EventRender& e if (output_.json.simple) { logger_->log_trace("Writing event in simple JSON"); - eventRender.json.simple = wel::jsonToString(wel::toJSON(doc, false)); + eventRender.json.simple = wel::jsonToString(wel::toSimpleJSON(doc)); logger_->log_trace("Finish writing in simple JSON"); } @@ -644,7 +644,7 @@ bool ConsumeWindowsEventLog::createEventRender(EVT_HANDLE hEvent, EventRender& e if (output_.json.flattened) { logger_->log_trace("Writing event in flattened JSON"); - eventRender.json.flattened = wel::jsonToString(wel::toJSON(doc, true)); + eventRender.json.flattened = wel::jsonToString(wel::toFlattenedJSON(doc)); logger_->log_trace("Finish writing in flattened JSON"); } diff --git a/extensions/windows-event-log/wel/JSONConverter.h b/extensions/windows-event-log/wel/JSONUtils.cpp similarity index 93% rename from extensions/windows-event-log/wel/JSONConverter.h rename to extensions/windows-event-log/wel/JSONUtils.cpp index 465656aeb67..de3d2e6ceaf 100644 --- a/extensions/windows-event-log/wel/JSONConverter.h +++ b/extensions/windows-event-log/wel/JSONUtils.cpp @@ -15,10 +15,7 @@ * limitations under the License. */ -#pragma once - -#undef RAPIDJSON_ASSERT -#define RAPIDJSON_ASSERT(x) if (!(x)) throw std::logic_error("rapidjson exception"); // NOLINT +#include "JSONUtils.h" #include #include @@ -39,7 +36,7 @@ namespace nifi { namespace minifi { namespace wel { -rapidjson::Value xmlElementToJSON(const pugi::xml_node& node, rapidjson::Document& doc) { +static rapidjson::Value xmlElementToJSON(const pugi::xml_node& node, rapidjson::Document& doc) { gsl_Expects(node.type() == pugi::xml_node_type::node_element); rapidjson::Value object(rapidjson::kObjectType); object.AddMember("name", rapidjson::StringRef(node.name()), doc.GetAllocator()); @@ -57,7 +54,7 @@ rapidjson::Value xmlElementToJSON(const pugi::xml_node& node, rapidjson::Documen return object; } -rapidjson::Value xmlDocumentToJSON(const pugi::xml_node& node, rapidjson::Document& doc) { +static rapidjson::Value xmlDocumentToJSON(const pugi::xml_node& node, rapidjson::Document& doc) { gsl_Expects(node.type() == pugi::xml_node_type::node_document); rapidjson::Value children(rapidjson::kArrayType); for (const auto& child : node.children()) { @@ -76,7 +73,7 @@ rapidjson::Document toRawJSON(const pugi::xml_node& root) { return doc; } -rapidjson::Document toJSON(const pugi::xml_node& root, bool flatten) { +static rapidjson::Document toJSONImpl(const pugi::xml_node& root, bool flatten) { rapidjson::Document doc{rapidjson::kObjectType}; auto event_xml = root.child("Event"); @@ -147,6 +144,14 @@ rapidjson::Document toJSON(const pugi::xml_node& root, bool flatten) { return doc; } +rapidjson::Document toSimpleJSON(const pugi::xml_node& root) { + return toJSONImpl(root, false); +} + +rapidjson::Document toFlattenedJSON(const pugi::xml_node& root) { + return toJSONImpl(root, true); +} + std::string jsonToString(rapidjson::Document& doc) { rapidjson::StringBuffer buffer; rapidjson::PrettyWriter writer(buffer); diff --git a/extensions/windows-event-log/wel/JSONUtils.h b/extensions/windows-event-log/wel/JSONUtils.h new file mode 100644 index 00000000000..78681f88112 --- /dev/null +++ b/extensions/windows-event-log/wel/JSONUtils.h @@ -0,0 +1,70 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#undef RAPIDJSON_ASSERT +#define RAPIDJSON_ASSERT(x) if (!(x)) throw std::logic_error("rapidjson exception"); // NOLINT + +#include + +#include "rapidjson/document.h" + +namespace org { +namespace apache { +namespace nifi { +namespace minifi { +namespace wel { + +/** + * Converts each xml element node to a json object of + * the form {name: String, attributes: Object, children: Array, text: String} + * Aims to preserve most of the input xml structure. + */ +rapidjson::Document toRawJSON(const pugi::xml_node& root); + +/** + * Retains some hierarchical structure of the original xml event, + * e.g. {System: {Provider: {Name: String, Guid: String}}} + */ +rapidjson::Document toSimpleJSON(const pugi::xml_node& root); + +/** + * Flattens most of the structure, i.e. removes intermediate + * objects and lifts innermost string-valued keys to the root. + * e.g. {System: {Provider: {Name: String}}} => {Name: String} + * + * Moreover it also flattens each named data element where the + * name does not conflict with already existing members + * (e.g. a data with name "Guid" won't be flattened as it would + * overwrite the existing "Guid" field). + * + * e.g. {EventData: [{Name: "Test", Content: "X"}]} => {Test: "X"} + * + * In order to mitigate data loss, it preserves the EventData + * array in its entirety as well. + * (otherwise a "Guid" data would be lost) + */ +rapidjson::Document toFlattenedJSON(const pugi::xml_node& root); + +std::string jsonToString(rapidjson::Document& doc); + +} // namespace wel +} // namespace minifi +} // namespace nifi +} // namespace apache +} // namespace org \ No newline at end of file