Files
scylladb/json/json_elements.hh
Amnon Heiman 1866091b3d Adding basic json support
This is a migration of the basic json support taken from the
osv/httpserver.

The routes uses the json object to return errors in a json format.

This also adds json_exception which has a constructor from an exception.

Signed-off-by: Amnon Heiman <amnon@cloudius-systems.com>
2015-03-08 21:55:57 +02:00

234 lines
5.5 KiB
C++

/*
* This file is open source software, licensed to you under the terms
* of the Apache License, Version 2.0 (the "License"). See the NOTICE file
* distributed with this work for additional information regarding copyright
* ownership. 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.
*/
/*
* Copyright 2015 Cloudius Systems
*/
#ifndef JSON_ELEMENTS_HH_
#define JSON_ELEMENTS_HH_
#include <string>
#include <vector>
#include <time.h>
#include <sstream>
#include "formatter.hh"
#include "core/sstring.hh"
namespace json {
/**
* The base class for all json element.
* Every json element has a name
* An indication if it was set or not
* And is this element is mandatory.
* When a mandatory element is not set
* this is not a valid object
*/
class json_base_element {
public:
/**
* The constructors
*/
json_base_element()
: _mandatory(false), _set(false) {
}
virtual ~json_base_element() = default;
/**
* Check if it's a mandatory parameter
* and if it's set.
* @return true if this is not a mandatory parameter
* or if it is and it's value is set
*/
virtual bool is_verify() {
return !(_mandatory && !_set);
}
/**
* returns the internal value in a json format
* Each inherit class must implement this method
* @return formated internal value
*/
virtual std::string to_string() = 0;
std::string _name;
bool _mandatory;
bool _set;
};
/**
* Basic json element instantiate
* the json_element template.
* it adds a value to the base definition
* and the to_string implementation using the formatter
*/
template<class T>
class json_element : public json_base_element {
public:
/**
* the assignment operator also set
* the set value to true.
* @param new_value the new value
* @return the value itself
*/
json_element &operator=(const T& new_value) {
_value = new_value;
_set = true;
return *this;
}
/**
* the assignment operator also set
* the set value to true.
* @param new_value the new value
* @return the value itself
*/
template<class C>
json_element &operator=(const C& new_value) {
_value = new_value;
_set = true;
return *this;
}
/**
* The brackets operator
* @return the value
*/
const T& operator()() const {
return _value;
}
/**
* The to_string return the value
* formated as a json value
* @return the value foramted for json
*/
virtual std::string to_string() override
{
return formatter::to_json(_value);
}
private:
T _value;
};
/**
* json_list is based on std vector implementation.
*
* When values are added with push it is set the "set" flag to true
* hence will be included in the parsed object
*/
template<class T>
class json_list : public json_base_element {
public:
/**
* Add an element to the list.
* @param element a new element that will be added to the list
*/
void push(const T& element) {
_set = true;
_elements.push_back(element);
}
virtual std::string to_string() override
{
return formatter::to_json(_elements);
}
std::vector<T> _elements;
};
class jsonable {
public:
virtual ~jsonable() = default;
/**
* create a foramted string of the object.
* @return the object formated.
*/
virtual std::string to_json() const = 0;
};
/**
* The base class for all json objects
* It holds a list of all the element in it,
* allowing it implement the to_json method.
*
* It also allows iterating over the element
* in the object, even if not all the member
* are known in advance and in practice mimic
* reflection
*/
struct json_base : public jsonable {
virtual ~json_base() = default;
json_base() = default;
json_base(const json_base&) = delete;
json_base operator=(const json_base&) = delete;
/**
* create a foramted string of the object.
* @return the object formated.
*/
virtual std::string to_json() const;
/**
* Check that all mandatory elements are set
* @return true if all mandatory parameters are set
*/
virtual bool is_verify() const;
/**
* Register an element in an object
* @param element the element to be added
* @param name the element name
* @param mandatory is this element mandatory.
*/
virtual void add(json_base_element* element, std::string name,
bool mandatory = false);
std::vector<json_base_element*> _elements;
};
/**
* The json return type, is a helper class to return a json
* formatted string.
* It uses autoboxing in its constructor so when a function return
* type is json_return_type, it could return a type that would be converted
* ie.
* json_return_type foo() {
* return "hello";
* }
*
* would return a json formatted string: "hello" (rather then hello)
*/
struct json_return_type {
sstring _res;
template<class T>
json_return_type(const T& res) {
_res = formatter::to_json(res);
}
};
}
#endif /* JSON_ELEMENTS_HH_ */