blob: bd0365aaa8f4392775e22592a0c1d947ba348934 [file] [log] [blame]
// 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
#include <string>
#include <rapidjson/document.h>
#include "kudu/gutil/ref_counted.h"
namespace kudu {
// A wrapper around rapidjson Value objects, to simplify usage.
// Intended solely for building json objects, not writing/parsing.
//
// Simplifies code like this:
//
// rapidjson::Document d;
// rapidjson::Value v;
// v.SetObject();
// rapidjson::Value list;
// list.SetArray();
// v.AddMember("list", list, d.GetAllocator());
// v["list"].PushBack(rapidjson::Value().SetString("element"), d.GetAllocator());
//
// To this:
//
// EasyJson ej;
// ej["list"][0] = "element";
//
// Client code should build objects as demonstrated above,
// then call EasyJson::value() to obtain a reference to the
// built rapidjson Value.
class EasyJson {
public:
// Used for initializing EasyJson's with complex types.
// For example:
//
// EasyJson array;
// EasyJson nested = array.PushBack(EasyJson::kObject);
// nested["attr"] = "val";
// // array = [ { "attr": "val" } ]
enum ComplexTypeInitializer {
kObject,
kArray
};
EasyJson();
// Initializes the EasyJson object with the given type.
explicit EasyJson(ComplexTypeInitializer type);
~EasyJson() = default;
// Returns the child EasyJson associated with key.
//
// Note: this method can mutate the EasyJson object
// as follows:
//
// If this EasyJson's underlying Value is not an object
// (i.e. !this->value().IsObject()), then its Value is
// coerced to an object, overwriting the old Value.
// If the given key does not exist, a Null-valued
// EasyJson associated with key is created.
EasyJson Get(const std::string& key);
// Returns the child EasyJson at index.
//
// Note: this method can mutate the EasyJson object
// as follows:
//
// If this EasyJson's underlying Value is not an array
// (i.e. !this->value().IsArray()), then its Value is
// coerced to an array, overwriting the old Value.
// If index >= this->value().Size(), then the underlying
// array's size is increased to index + 1 (new indices
// are filled with Null values).
EasyJson Get(int index);
// Same as Get(key).
EasyJson operator[](const std::string& key);
// Same as Get(index).
EasyJson operator[](int index);
// Sets the underlying Value equal to val.
// Returns a reference to the object itself.
//
// 'val' can be a bool, int32_t, int64_t, double,
// char*, string, or ComplexTypeInitializer.
EasyJson& operator=(const std::string& val);
template<typename T>
EasyJson& operator=(T val);
// Sets the underlying Value to an object.
// Returns a reference to the object itself.
//
// i.e. after calling SetObject(),
// value().IsObject() == true
EasyJson& SetObject();
// Sets the underlying Value to an array.
// Returns a reference to the object itself.
//
// i.e. after calling SetArray(),
// value().IsArray() == true
EasyJson& SetArray();
// Associates val with key.
// Returns the child object.
//
// If this EasyJson's underlying Value is not an object
// (i.e. !this->value().IsObject()), then its Value is
// coerced to an object, overwriting the old Value.
// If the given key does not exist, a new child entry
// is created with the given value.
EasyJson Set(const std::string& key, const std::string& val);
template<typename T>
EasyJson Set(const std::string& key, T val);
// Stores val at index.
// Returns the child object.
//
// If this EasyJson's underlying Value is not an array
// (i.e. !this->value().IsArray()), then its Value is
// coerced to an array, overwriting the old Value.
// If index >= this->value().Size(), then the underlying
// array's size is increased to index + 1 (new indices
// are filled with Null values).
EasyJson Set(int index, const std::string& val);
template<typename T>
EasyJson Set(int index, T val);
// Appends val to the underlying array.
// Returns a reference to the new child object.
//
// If this EasyJson's underlying Value is not an array
// (i.e. !this->value().IsArray()), then its Value is
// coerced to an array, overwriting the old Value.
EasyJson PushBack(const std::string& val);
template<typename T>
EasyJson PushBack(T val);
// Returns a reference to the underlying Value.
rapidjson::Value& value() const { return *value_; }
// Returns a string representation of the underlying json.
std::string ToString() const;
private:
// One instance of EasyJsonAllocator is shared among a root
// EasyJson object and all of its descendants. The allocator
// owns the underlying rapidjson Value, and a rapidjson
// allocator (via a rapidjson::Document).
class EasyJsonAllocator : public RefCounted<EasyJsonAllocator> {
public:
rapidjson::Value& value() { return value_; }
rapidjson::Document::AllocatorType& allocator() { return value_.GetAllocator(); }
private:
friend class RefCounted<EasyJsonAllocator>;
~EasyJsonAllocator() = default;
// The underlying rapidjson::Value object (Document is
// a subclass of Value that has its own allocator).
rapidjson::Document value_;
};
// Used to instantiate descendant objects.
EasyJson(rapidjson::Value* value, scoped_refptr<EasyJsonAllocator> alloc);
// One allocator is shared among an EasyJson object and
// all of its descendants.
scoped_refptr<EasyJsonAllocator> alloc_;
// A pointer to the underlying Value in the object
// tree owned by alloc_.
rapidjson::Value* value_;
};
} // namespace kudu