JSON Voorhees
Killer JSON for C++
Loading...
Searching...
No Matches
enum_adapter.hpp
Go to the documentation of this file.
1/// \file jsonv/serialization/enum_adapter.hpp
2///
3/// Copyright (c) 2015-2020 by Travis Gockel. All rights reserved.
4///
5/// This program is free software: you can redistribute it and/or modify it under the terms of the Apache License
6/// as published by the Apache Software Foundation, either version 2 of the License, or (at your option) any later
7/// version.
8///
9/// \author Travis Gockel (travis@gockelhut.com)
10#pragma once
11
12#include <jsonv/config.hpp>
13#include <jsonv/functional.hpp>
15
16#include "adapter_for.hpp"
17
18namespace jsonv
19{
20
21/// \addtogroup Serialization
22/// \{
23
24/// An adapter for enumeration types. The most common use of this is to map \c enum values in C++ to string values in a
25/// JSON representation (and vice versa).
26///
27/// \tparam TEnum The type to map. This is not restricted to C++ enumerations (types defined with the \c enum keyword),
28/// but any type you wish to restrict to a subset of values.
29/// \tparam FEnumComp <tt>bool (*)(TEnum, TEnum)</tt> -- a strict ordering for \c TEnum values.
30/// \tparam FValueComp <tt>bool (*)(value, value)</tt> -- a strict ordering for \c value objects. By default, this is a
31/// case-sensitive comparison, but this can be replaced with anything you desire (for example, use
32/// \c value_less_icase to ignore case in extracting from JSON).
33///
34/// \see enum_adapter_icase
35template <typename TEnum,
36 typename FEnumComp = std::less<TEnum>,
37 typename FValueComp = std::less<value>
38 >
40 public adapter_for<TEnum>
41{
42public:
43 /// Create an adapter with mapping values from the range <tt>[first, last)</tt>.
44 ///
45 /// \tparam TForwardIterator An iterator yielding the type <tt>std::pair<jsonv::value, TEnum>></tt>
46 template <typename TForwardIterator>
48 _enum_name(std::move(enum_name))
49 {
50 for (auto iter = first; iter != last; ++iter)
51 {
52 _val_to_cpp.insert({ iter->second, iter->first });
53 _cpp_to_val.insert(*iter);
54 }
55 }
56
57 /// Create an adapter with the specified \a mapping values.
58 ///
59 /// \param enum_name A user-friendly name for this enumeration to be used in error messages.
60 /// \param mapping A list of C++ types and values to use in \c to_json and \c extract. It is okay to have a C++
61 /// value with more than one JSON representation. In this case, the \e first JSON representation will
62 /// be used in \c to_json, but \e all JSON representations will be interpreted as the C++ value. It
63 /// is also okay to have the same JSON representation for multiple C++ values. In this case, the
64 /// \e first JSON representation provided for that value will be used in \c extract.
65 ///
66 /// \example "Serialization: Enum Adapter"
67 /// \code
68 /// enum_adapter<ring>("ring",
69 /// {
70 /// { ring::fire, "fire" },
71 /// { ring::wind, "wind" },
72 /// { ring::earth, "earth" },
73 /// { ring::water, "water" },
74 /// { ring::heart, "heart" }, // "heart" is preferred for to_json
75 /// { ring::heart, "useless" }, // "useless" is interpreted as ring::heart in extract
76 /// }
77 /// );
78 /// \endcode
79 explicit enum_adapter(std::string enum_name, std::initializer_list<std::pair<TEnum, value>> mapping) :
80 enum_adapter(std::move(enum_name), mapping.begin(), mapping.end())
81 { }
82
83protected:
84 virtual TEnum create(const extraction_context& context, const value& from) const override
85 {
86 using std::end;
87
88 auto iter = _val_to_cpp.find(from);
89 if (iter != end(_val_to_cpp))
90 return iter->second;
91 else
92 throw extraction_error(context.path(),
93 std::string("Invalid value for ") + _enum_name + ": " + to_string(from)
94 );
95 }
96
97 virtual value to_json(const serialization_context&, const TEnum& from) const override
98 {
99 using std::end;
100
101 auto iter = _cpp_to_val.find(from);
102 if (iter != end(_cpp_to_val))
103 return iter->second;
104 else
105 return null;
106 }
107
108private:
109 std::string _enum_name;
110 std::map<value, TEnum, FValueComp> _val_to_cpp;
111 std::map<TEnum, value, FEnumComp> _cpp_to_val;
112};
113
114/// An adapter for enumeration types which ignores the case when extracting from JSON.
115///
116/// \see enum_adapter
117template <typename TEnum, typename FEnumComp = std::less<TEnum>>
119
120/// \}
121
122}
An adapter for the type T.
An adapter for enumeration types.
enum_adapter(std::string enum_name, TForwardIterator first, TForwardIterator last)
Create an adapter with mapping values from the range [first, last).
Copyright (c) 2014-2020 by Travis Gockel.
A collection of function objects a la &lt;functional&gt;.
JSONV_PUBLIC const value null
An instance with kind::null.
STL namespace.
Conversion between C++ types and JSON values.