DAW JSON Link
Loading...
Searching...
No Matches
daw_from_json.h
Go to the documentation of this file.
1// Copyright (c) Darrell Wright
2//
3// Distributed under the Boost Software License, version 1.0. (see accompanying
4// file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
5//
6// Official repository: https://github.com/beached/daw_json_link
7//
8
9#pragma once
10
11#include "impl/version.h"
12
13#include "daw_from_json_fwd.h"
16#include "impl/daw_json_value.h"
17
18#include <daw/daw_data_end.h>
19#include <daw/traits/daw_traits_conditional.h>
20
21#include <daw/stdinc/data_access.h>
22#include <daw/stdinc/move_fwd_exch.h>
23#include <string_view>
24
25namespace daw::json {
26 inline namespace DAW_JSON_VER {
27
36 template<typename JsonMember, bool KnownBounds, typename String,
37 auto... PolicyFlags>
38 [[nodiscard]] constexpr auto
39 from_json( String &&json_data, options::parse_flags_t<PolicyFlags...> ) {
40 static_assert(
41 json_details::is_string_view_like_v<String>,
42 "String type must have a be a contiguous range of Characters" );
43 daw_json_ensure( std::data( json_data ) != nullptr,
44 ErrorReason::EmptyJSONDocument );
45 daw_json_ensure( std::size( json_data ) != 0,
46 ErrorReason::EmptyJSONDocument );
47
48 static_assert(
49 json_details::has_json_deduced_type_v<JsonMember>,
50 "Missing specialization of daw::json::json_data_contract for class "
51 "mapping or specialization of daw::json::json_link_basic_type_map" );
52 using json_member = json_details::json_deduced_type<JsonMember>;
53 using ParsePolicy =
54 BasicParsePolicy<options::parse_flags_t<PolicyFlags...>::value>;
55
58 using policy_zstring_t = json_details::apply_zstring_policy_option_t<
59 ParsePolicy, String, options::ZeroTerminatedString::yes>;
60
61 using ParseState =
62 daw::conditional_t<policy_zstring_t::is_default_parse_policy,
63 DefaultParsePolicy, policy_zstring_t>;
64 auto first = std::data( json_data );
65 auto last = daw::data_end( json_data );
66 if( first != last and last[-1] == 0 ) {
67 --last;
68 }
69 auto parse_state = ParseState( first, last );
70
71 if constexpr( ParseState::must_verify_end_of_data_is_valid ) {
72 auto result =
73 json_details::parse_value<json_member, KnownBounds,
74 json_member::expected_type>( parse_state );
75 parse_state.trim_left( );
76 daw_json_ensure( parse_state.empty( ), ErrorReason::InvalidEndOfValue,
77 parse_state );
78 return result;
79 } else {
80 return json_details::parse_value<json_member, KnownBounds,
81 json_member::expected_type>(
82 parse_state );
83 }
84 }
85
94 template<typename JsonMember, bool KnownBounds, typename String>
95 [[nodiscard]] constexpr auto from_json( String &&json_data ) {
96 static_assert(
97 json_details::is_string_view_like_v<String>,
98 "String type must have a be a contiguous range of Characters" );
99 return from_json<JsonMember, KnownBounds>( DAW_FWD( json_data ),
100 options::parse_flags<> );
101 }
102
111 template<typename JsonMember, bool KnownBounds, typename String,
112 typename Allocator, auto... PolicyFlags>
113 [[nodiscard]] constexpr auto
114 from_json_alloc( String &&json_data, Allocator const &alloc,
115 options::parse_flags_t<PolicyFlags...> ) {
116 static_assert(
117 json_details::is_string_view_like_v<String>,
118 "String type must have a be a contiguous range of Characters" );
119 daw_json_ensure( std::size( json_data ) != 0,
120 ErrorReason::EmptyJSONDocument );
121 daw_json_ensure( std::data( json_data ) != nullptr,
122 ErrorReason::EmptyJSONPath );
123
124 using json_member = json_details::json_deduced_type<JsonMember>;
125
126 static_assert(
127 json_details::has_unnamed_default_type_mapping_v<JsonMember>,
128 "Missing specialization of daw::json::json_data_contract for class "
129 "mapping or specialization of daw::json::json_link_basic_type_map" );
130
131 char const *f = std::data( json_data );
132 char const *l = daw::data_end( json_data );
133 Allocator a = alloc;
134
135 using ParsePolicy =
136 BasicParsePolicy<options::parse_flags_t<PolicyFlags...>::value>;
137
140 using ParseState = json_details::apply_zstring_policy_option_t<
141 ParsePolicy, String, options::ZeroTerminatedString::yes>;
142
143 auto parse_state = ParseState::with_allocator( f, l, a );
144 if constexpr( ParseState::must_verify_end_of_data_is_valid ) {
145 auto result =
146 json_details::parse_value<json_member, KnownBounds,
147 json_member::expected_type>( parse_state );
148 parse_state.trim_left( );
149 daw_json_ensure( parse_state.empty( ), ErrorReason::InvalidEndOfValue,
150 parse_state );
151 return result;
152 } else {
153 return json_details::parse_value<json_member, KnownBounds,
154 json_member::expected_type>(
155 parse_state );
156 }
157 }
158
167 template<typename JsonMember, bool KnownBounds, typename String,
168 typename Allocator>
169 [[nodiscard]] constexpr auto from_json_alloc( String &&json_data,
170 Allocator const &alloc ) {
171 static_assert(
172 json_details::is_string_view_like_v<String>,
173 "String type must have a be a contiguous range of Characters" );
174 return from_json_alloc<JsonMember, KnownBounds>(
175 DAW_FWD( json_data ), alloc, options::parse_flags<> );
176 }
177
188 template<typename JsonMember, bool KnownBounds, typename String,
189 auto... PolicyFlags>
190 [[nodiscard]] constexpr auto
191 from_json( String &&json_data, std::string_view member_path,
192 options::parse_flags_t<PolicyFlags...> ) {
193 static_assert(
194 json_details::is_string_view_like_v<String>,
195 "String type must have a be a contiguous range of Characters" );
196
197 daw_json_ensure( std::size( json_data ) != 0,
198 ErrorReason::EmptyJSONDocument );
199 daw_json_ensure( std::data( json_data ) != nullptr,
200 ErrorReason::EmptyJSONPath );
201 daw_json_ensure( std::data( member_path ) != nullptr,
202 ErrorReason::EmptyJSONPath );
203
204 using json_member = json_details::json_deduced_type<JsonMember>;
205 static_assert(
206 json_details::has_unnamed_default_type_mapping_v<JsonMember>,
207 "Missing specialization of daw::json::json_data_contract for class "
208 "mapping or specialization of daw::json::json_link_basic_type_map" );
209
210 using ParsePolicy =
211 BasicParsePolicy<options::parse_flags_t<PolicyFlags...>::value>;
212
215 using policy_zstring_t = json_details::apply_zstring_policy_option_t<
216 ParsePolicy, String, options::ZeroTerminatedString::yes>;
217
218 using ParseState =
219 daw::conditional_t<policy_zstring_t::is_default_parse_policy,
220 DefaultParsePolicy, policy_zstring_t>;
221 auto first = std::data( json_data );
222 auto last = daw::data_end( json_data );
223 if( first != last and last[-1] == 0 ) {
224 --last;
225 }
226 auto jv = basic_json_value( ParseState( first, last ) );
227 jv = jv.find_member( member_path );
228
229 if constexpr( json_details::is_json_nullable_v<json_member> ) {
230 if( not jv ) {
231 return json_details::construct_nullable_empty<
232 json_details::json_constructor_t<json_member>>( );
233 }
234 } else {
235 daw_json_ensure( jv, ErrorReason::JSONPathNotFound );
236 }
237 auto parse_state = jv.get_raw_state( );
238 if constexpr( ParseState::must_verify_end_of_data_is_valid ) {
239 auto result =
240 json_details::parse_value<json_member, KnownBounds,
241 json_member::expected_type>( parse_state );
242 parse_state.trim_left( );
243 daw_json_ensure( parse_state.empty( ), ErrorReason::InvalidEndOfValue,
244 parse_state );
245 return result;
246 } else {
247 return json_details::parse_value<json_member, KnownBounds,
248 json_member::expected_type>(
249 parse_state );
250 }
251 }
252
263 template<typename JsonMember, bool KnownBounds, typename String>
264 [[nodiscard]] constexpr auto from_json( String &&json_data,
265 std::string_view member_path ) {
266 static_assert(
267 json_details::is_string_view_like_v<String>,
268 "String type must have a be a contiguous range of Characters" );
269
270 return from_json<JsonMember, KnownBounds>(
271 DAW_FWD( json_data ), member_path, options::parse_flags<> );
272 }
273
284 template<typename JsonMember, bool KnownBounds, typename String,
285 typename Allocator, auto... PolicyFlags>
286 [[nodiscard]] constexpr auto
287 from_json_alloc( String &&json_data, std::string_view member_path,
288 Allocator const &alloc,
289 options::parse_flags_t<PolicyFlags...> ) {
290
291 static_assert(
292 json_details::is_string_view_like_v<String>,
293 "String type must have a be a contiguous range of Characters" );
294 daw_json_ensure( std::size( json_data ) != 0,
295 ErrorReason::EmptyJSONDocument );
296 daw_json_ensure( std::data( json_data ) != nullptr,
297 ErrorReason::EmptyJSONDocument );
298 daw_json_ensure( std::data( member_path ) != nullptr,
299 ErrorReason::EmptyJSONPath );
300
301 using json_member = json_details::json_deduced_type<JsonMember>;
302 static_assert(
303 json_details::has_unnamed_default_type_mapping_v<JsonMember>,
304 "Missing specialization of daw::json::json_data_contract for class "
305 "mapping or specialization of daw::json::json_link_basic_type_map" );
306
307 using ParsePolicy =
308 BasicParsePolicy<options::parse_flags_t<PolicyFlags...>::value>;
309
312 using ParseState = json_details::apply_zstring_policy_option_t<
313 ParsePolicy, String, options::ZeroTerminatedString::yes>;
314
315 auto first = std::data( json_data );
316 auto last = daw::data_end( json_data );
317 if( first != last and last[-1] == 0 ) {
318 --last;
319 }
320 auto jv = basic_json_value(
321 ParseState( first, last, first, last ).with_allocator( alloc ) );
322 jv = jv.find_member( member_path );
323
324 if constexpr( json_details::is_json_nullable_v<json_member> ) {
325 if( not jv ) {
326 return json_details::construct_nullable_empty<
327 json_details::json_constructor_t<json_member>>( );
328 }
329 } else {
330 daw_json_ensure( jv, ErrorReason::JSONPathNotFound );
331 }
332 auto parse_state = jv.get_raw_state( );
333 if constexpr( ParseState::must_verify_end_of_data_is_valid ) {
334 auto result =
335 json_details::parse_value<json_member, KnownBounds,
336 json_member::expected_type>( parse_state );
337 parse_state.trim_left( );
338 daw_json_ensure( parse_state.empty( ), ErrorReason::InvalidEndOfValue,
339 parse_state );
340 return result;
341 } else {
342 return json_details::parse_value<json_member, KnownBounds,
343 json_member::expected_type>(
344 parse_state );
345 }
346 }
347
358 template<typename JsonMember, bool KnownBounds, typename String,
359 typename Allocator>
360 [[nodiscard]] constexpr auto from_json_alloc( String &&json_data,
361 std::string_view member_path,
362 Allocator const &alloc ) {
363 static_assert(
364 json_details::is_string_view_like_v<String>,
365 "String type must have a be a contiguous range of Characters" );
366
367 return from_json_alloc<JsonMember, KnownBounds>(
368 DAW_FWD( json_data ), member_path, alloc, options::parse_flags<> );
369 }
370
378 template<typename JsonMember, bool KnownBounds, json_options_t P,
379 typename Allocator, auto... PolicyFlags>
380 [[nodiscard]] inline constexpr auto
382 options::parse_flags_t<PolicyFlags...> ) {
383 using json_member = json_details::json_deduced_type<JsonMember>;
384 static_assert(
385 json_details::has_unnamed_default_type_mapping_v<JsonMember>,
386 "Missing specialization of daw::json::json_data_contract for class "
387 "mapping or specialization of daw::json::json_link_basic_type_map" );
388 using ParsePolicy = typename BasicParsePolicy<
389 P, Allocator>::template SetPolicyOptions<PolicyFlags...>;
390 using ParseState =
391 daw::conditional_t<ParsePolicy::is_default_parse_policy,
392 DefaultParsePolicy, ParsePolicy>;
393 auto const old_parse_state = value.get_raw_state( );
394 auto parse_state =
395 ParseState( old_parse_state.first, old_parse_state.last,
396 old_parse_state.class_first, old_parse_state.class_last,
397 old_parse_state.get_allocator( ) );
398
399 return json_details::parse_value<json_member, KnownBounds,
400 json_member::expected_type>(
401 parse_state );
402 }
403
411 template<typename JsonMember, bool KnownBounds, json_options_t PolicyFlags,
412 typename Allocator>
413 [[nodiscard]] inline constexpr auto
415
416 return from_json<JsonMember, KnownBounds>( std::move( value ),
417 options::parse_flags<> );
418 }
419
430 template<typename JsonMember, bool KnownBounds, json_options_t P,
431 typename Allocator, auto... PolicyFlags>
432 [[nodiscard]] constexpr auto
434 std::string_view member_path,
435 options::parse_flags_t<PolicyFlags...> ) {
436 using json_member = json_details::json_deduced_type<JsonMember>;
437 static_assert(
438 json_details::has_unnamed_default_type_mapping_v<JsonMember>,
439 "Missing specialization of daw::json::json_data_contract for class "
440 "mapping or specialization of daw::json::json_link_basic_type_map" );
441 using ParsePolicy =
442 BasicParsePolicy<options::parse_flags_t<PolicyFlags...>::value>;
443 auto const old_parse_state = value.get_raw_state( );
444 using ParseState =
445 daw::conditional_t<ParsePolicy::is_default_parse_policy,
446 DefaultParsePolicy, ParsePolicy>;
447 auto jv = basic_json_value(
448 ParseState( old_parse_state.first, old_parse_state.last,
449 old_parse_state.class_first, old_parse_state.class_last,
450 old_parse_state.get_allocator( ) ) );
451
452 jv = jv.find_member( member_path );
453
454 if constexpr( json_details::is_json_nullable_v<json_member> ) {
455 if( not jv ) {
456 return json_details::construct_nullable_empty<
457 json_details::json_constructor_t<json_member>>( );
458 }
459 } else {
460 daw_json_ensure( jv, ErrorReason::JSONPathNotFound );
461 }
462 auto parse_state = jv.get_raw_state( );
463 return json_details::parse_value<json_member, KnownBounds,
464 json_member::expected_type>(
465 parse_state );
466 }
467
478 template<typename JsonMember, bool KnownBounds, json_options_t PolicyFlags,
479 typename Allocator>
480 [[nodiscard]] constexpr auto from_json( basic_json_value<PolicyFlags> value,
481 std::string_view member_path ) {
482 return from_json<JsonMember, KnownBounds>(
483 std::move( value ), member_path, options::parse_flags<> );
484 }
485
496 template<typename JsonElement, typename Container, typename Constructor,
497 bool KnownBounds, typename String, auto... PolicyFlags>
498 [[nodiscard]] constexpr Container
499 from_json_array( String &&json_data,
500 options::parse_flags_t<PolicyFlags...> ) {
501 static_assert(
502 json_details::is_string_view_like_v<String>,
503 "String type must have a be a contiguous range of Characters" );
504
505 daw_json_ensure( std::size( json_data ) != 0,
506 ErrorReason::EmptyJSONDocument );
507 daw_json_ensure( std::data( json_data ) != nullptr,
508 ErrorReason::EmptyJSONPath );
509 static_assert(
510 json_details::has_unnamed_default_type_mapping_v<JsonElement>,
511 "Missing specialization of daw::json::json_data_contract for class "
512 "mapping or specialization of daw::json::json_link_basic_type_map" );
513 using element_type = json_details::json_deduced_type<JsonElement>;
514 static_assert( not std::is_same_v<element_type, void>,
515 "Unknown JsonElement type." );
516
517 using parser_t =
518 json_base::json_array<JsonElement, Container, Constructor>;
519
520 using ParsePolicy =
521 BasicParsePolicy<options::parse_flags_t<PolicyFlags...>::value>;
522
525 using policy_zstring_t = json_details::apply_zstring_policy_option_t<
526 ParsePolicy, String, options::ZeroTerminatedString::yes>;
527
528 using ParseState =
529 daw::conditional_t<policy_zstring_t::is_default_parse_policy,
530 DefaultParsePolicy, policy_zstring_t>;
531 auto parse_state =
532 ParseState{ std::data( json_data ), daw::data_end( json_data ) };
533
534 parse_state.trim_left_unchecked( );
535#if defined( DAW_JSON_BUGFIX_FROM_JSON_001 )
536 daw_json_ensure( parse_state.is_opening_bracket_checked( ),
537 ErrorReason::InvalidArrayStart, parse_state );
538#else
539 daw_json_assert_weak( parse_state.is_opening_bracket_checked( ),
540 ErrorReason::InvalidArrayStart, parse_state );
541#endif
542 if constexpr( ParseState::must_verify_end_of_data_is_valid ) {
543 auto result =
544 json_details::parse_value_array<parser_t, KnownBounds>( parse_state );
545 parse_state.trim_left( );
546 daw_json_ensure( parse_state.empty( ), ErrorReason::InvalidEndOfValue,
547 parse_state );
548 return result;
549 } else {
550 return json_details::parse_value_array<parser_t, KnownBounds>(
551 parse_state );
552 }
553 }
554
565 template<typename JsonElement, typename Container, typename Constructor,
566 bool KnownBounds, typename String>
567 [[nodiscard]] constexpr Container from_json_array( String &&json_data ) {
568 static_assert(
569 json_details::is_string_view_like_v<String>,
570 "String type must have a be a contiguous range of Characters" );
571 return from_json_array<JsonElement, Container, Constructor, KnownBounds>(
572 DAW_FWD( json_data ), options::parse_flags<> );
573 }
574
588 template<typename JsonElement, typename Container, typename Constructor,
589 bool KnownBounds, typename String, auto... PolicyFlags>
590 [[nodiscard]] constexpr Container
591 from_json_array( String &&json_data, std::string_view member_path,
592 options::parse_flags_t<PolicyFlags...> ) {
593 static_assert(
594 json_details::is_string_view_like_v<String>,
595 "String type must have a be a contiguous range of Characters" );
596
597 daw_json_ensure( std::size( json_data ) != 0,
598 ErrorReason::EmptyJSONDocument );
599 daw_json_ensure( std::data( json_data ) != nullptr,
600 ErrorReason::EmptyJSONPath );
601 daw_json_ensure( std::data( member_path ) != nullptr,
602 ErrorReason::EmptyJSONPath );
603 static_assert(
604 json_details::has_unnamed_default_type_mapping_v<JsonElement>,
605 "Missing specialization of daw::json::json_data_contract for class "
606 "mapping or specialization of daw::json::json_link_basic_type_map" );
607 using element_type = json_details::json_deduced_type<JsonElement>;
608 static_assert( not std::is_same_v<element_type, void>,
609 "Unknown JsonElement type." );
610
611 using parser_t =
612 json_base::json_array<JsonElement, Container, Constructor>;
613
614 using ParsePolicy =
615 BasicParsePolicy<options::parse_flags_t<PolicyFlags...>::value>;
616
619 using policy_zstring_t = json_details::apply_zstring_policy_option_t<
620 ParsePolicy, String, options::ZeroTerminatedString::yes>;
621
622 using ParseState =
623 daw::conditional_t<policy_zstring_t::is_default_parse_policy,
624 DefaultParsePolicy, policy_zstring_t>;
625 auto first = std::data( json_data );
626 auto last = daw::data_end( json_data );
627 if( first != last and last[-1] == 0 ) {
628 --last;
629 }
630 auto jv = basic_json_value( ParseState( first, last ) );
631 jv = jv.find_member( member_path );
632
633 if constexpr( json_details::is_json_nullable_v<parser_t> ) {
634 if( not jv ) {
635 return json_details::construct_nullable_empty<
636 json_details::json_constructor_t<parser_t>>( );
637 }
638 } else {
639 daw_json_ensure( jv, ErrorReason::JSONPathNotFound );
640 }
641 auto parse_state = jv.get_raw_state( );
642 parse_state.trim_left_unchecked( );
643#if defined( DAW_JSON_BUGFIX_FROM_JSON_001 )
644 daw_json_ensure( parse_state.is_opening_bracket_checked( ),
645 ErrorReason::InvalidArrayStart, parse_state );
646#else
647 daw_json_assert_weak( parse_state.is_opening_bracket_checked( ),
648 ErrorReason::InvalidArrayStart, parse_state );
649#endif
650 if constexpr( ParseState::must_verify_end_of_data_is_valid ) {
651 auto result =
652 json_details::parse_value_array<parser_t, KnownBounds>( parse_state );
653 parse_state.trim_left( );
654 daw_json_ensure( parse_state.empty( ), ErrorReason::InvalidEndOfValue,
655 parse_state );
656 return result;
657 } else {
658 return json_details::parse_value_array<parser_t, KnownBounds>(
659 parse_state );
660 }
661 }
662
676 template<typename JsonElement, typename Container, typename Constructor,
677 bool KnownBounds, typename String>
678 [[nodiscard]] constexpr Container
679 from_json_array( String &&json_data, std::string_view member_path ) {
680 static_assert(
681 json_details::is_string_view_like_v<String>,
682 "String type must have a be a contiguous range of Characters" );
683
684 return from_json_array<JsonElement, Container, Constructor, KnownBounds>(
685 DAW_FWD( json_data ), member_path, options::parse_flags<> );
686 }
687 } // namespace DAW_JSON_VER
688} // namespace daw::json
#define daw_json_assert_weak(Bool,...)
Assert that Bool is true when in Checked Input mode If false pass rest of args to daw_json_error.
#define daw_json_ensure(Bool,...)
Ensure that Bool is true. If false pass rest of args to daw_json_error.
constexpr Container from_json_array(String &&json_data, options::parse_flags_t< PolicyFlags... >)
Parse JSON data where the root item is an array.
constexpr auto from_json(String &&json_data, options::parse_flags_t< PolicyFlags... >)
Construct the JSONMember from the JSON document argument.
constexpr auto from_json_alloc(String &&json_data, Allocator const &alloc, options::parse_flags_t< PolicyFlags... >)
Construct the JSONMember from the JSON document argument.
Customization point traits.
Handles the bounds and policy items for parsing execution and comments.
A non-owning container for arbitrary JSON values that allows movement/iteration through.
#define DAW_JSON_VER
The version string used in namespace definitions. Must be a valid namespace name.
Definition version.h:20