JSON Voorhees
Killer JSON for C++
Loading...
Searching...
No Matches
deserializer_construction.hpp
Go to the documentation of this file.
1/// \file jsonv/serialization/deserializer_construction.hpp
2///
3/// Copyright (c) 2015-2026 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>
14
15#include <concepts>
16#include <expected>
17#include <new>
18
19namespace jsonv
20{
21
22/// \addtogroup Serialization
23/// \{
24
25/// A \c deserializer for a type \c T with a deserializing constructor.
26///
27/// Four constructor shapes are accepted, preferred in this order: <tt>T(reader&, deserialization_context&)</tt>,
28/// <tt>T(reader&)</tt>, <tt>T(const value&, deserialization_context&)</tt> and <tt>T(const value&)</tt>. The last two
29/// are the shapes which predate deserialization running off a \c reader; they are handed a subtree materialised by
30/// \c read_value, so they keep working but pay for the tree they were always paying for.
31template <typename T>
33 public deserializer
34{
35public:
36 /// \see deserializer::get_type
38 virtual const std::type_info& get_type() const noexcept override
39 {
40 return typeid(T);
41 }
42
43 /// \see deserializer::deserialize
45 virtual std::expected<void, ast_node_type>
46 deserialize(deserialization_context& context, reader& from, void* into) const override
47 {
48 if constexpr (std::constructible_from<T, reader&, deserialization_context&>)
49 {
50 new(into) T(from, context);
51 }
52 else if constexpr (std::constructible_from<T, reader&>)
53 {
54 new(into) T(from);
55 }
56 else if constexpr (std::constructible_from<T, const value&, deserialization_context&>)
57 {
58 detail::borrowed_subtree subtree(context, from);
59 new(into) T(subtree.get(), context);
60 subtree.commit();
61 }
62 else
63 {
64 static_assert(std::constructible_from<T, const value&>,
65 "deserializer_construction<T> requires T to be constructible from "
66 "(reader&, deserialization_context&), (reader&), "
67 "(const value&, deserialization_context&) or (const value&)"
68 );
69
70 detail::borrowed_subtree subtree(context, from);
71 new(into) T(subtree.get());
72 subtree.commit();
73 }
74
75 // A constructor which fails does so by throwing, and a throwing placement-new constructs nothing, so there is
76 // never a half-built object in `into` to clean up here. deserialization_context::deserialize turns the
77 // exception into a problem on the context.
78 return {};
79 }
80};
81
82/// \}
83
84}
Provides extra information to routines used for deserialization and serialization.
Definition context.hpp:26
Provides extra information to routines used for deserialization, collects the problems they encounter...
A deserializer for a type T with a deserializing constructor.
virtual std::expected< void, ast_node_type > deserialize(deserialization_context &context, reader &from, void *into) const override
virtual const std::type_info & get_type() const noexcept override
A deserializer holds the method for converting JSON source into an arbitrary C++ type.
A reader instance reads from some form of JSON source (probably a string) and converts it into a JSON...
Definition reader.hpp:105
Copyright (c) 2014-2020 by Travis Gockel.
Deserialization of C++ types from a JSON AST.
#define JSONV_NODISCARD
Warn if the caller discards the result of this function.
Definition config.hpp:132