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
12
17
18#include <daw/daw_data_end.h>
19#include <daw/daw_not_null.h>
20#include <daw/traits/daw_traits_conditional.h>
21
22#include <daw/stdinc/data_access.h>
23#include <daw/stdinc/move_fwd_exch.h>
24#include <string_view>
25
26namespace daw::json {
27 inline namespace DAW_JSON_VER {
28
37 template<typename JsonMember, bool KnownBounds, typename String,
38 auto... PolicyFlags>
39 [[nodiscard]] constexpr auto
40 from_json( String &&json_data, options::parse_flags_t<PolicyFlags...> ) {
41 static_assert(
42 json_details::is_string_view_like_v<String>,
43 "String type must have a be a contiguous range of Characters" );
44 daw_json_ensure( std::size( json_data ) != 0,
45 ErrorReason::EmptyJSONDocument );
46
47 static_assert(
48 json_details::has_json_deduced_type_v<JsonMember>,
49 "Missing specialization of daw::json::json_data_contract for class "
50 "mapping or specialization of daw::json::json_link_basic_type_map" );
51 using json_member = json_details::json_deduced_type<JsonMember>;
52 using ParsePolicy =
53 BasicParsePolicy<options::parse_flags_t<PolicyFlags...>::value>;
54
57 using policy_zstring_t = json_details::apply_zstring_policy_option_t<
58 ParsePolicy,
59 String,
60 options::ZeroTerminatedString::yes>;
61
62 auto first = daw::not_null<char const *>( std::data( json_data ) );
63 auto last = daw::not_null<char const *>( daw::data_end( json_data ) );
64 if( first != last and last[-1] == 0 ) {
65 --last;
66 }
67
68 using ParseState =
69 daw::conditional_t<policy_zstring_t::is_default_parse_policy,
71 policy_zstring_t>;
72
73 auto parse_state = ParseState( first.get( ), last.get( ) );
74
75 if constexpr( ParseState::must_verify_end_of_data_is_valid ) {
76 auto result =
77 json_details::parse_value<json_member,
78 KnownBounds,
79 json_member::expected_type>( parse_state );
80 parse_state.trim_left( );
82 parse_state.empty( ), ErrorReason::InvalidEndOfValue, parse_state );
83 return result;
84 } else {
85 return json_details::
86 parse_value<json_member, KnownBounds, json_member::expected_type>(
87 parse_state );
88 }
89 }
90
99 template<typename JsonMember, bool KnownBounds, typename String>
100 [[nodiscard]] constexpr auto from_json( String &&json_data ) {
101 static_assert(
102 json_details::is_string_view_like_v<String>,
103 "String type must have a be a contiguous range of Characters" );
104 return from_json<JsonMember, KnownBounds>( DAW_FWD( json_data ),
105 options::parse_flags<> );
106 }
107
116 template<typename JsonMember, bool KnownBounds, typename String,
117 typename Allocator, auto... PolicyFlags>
118 [[nodiscard]] constexpr auto
119 from_json_alloc( String &&json_data, Allocator const &alloc,
120 options::parse_flags_t<PolicyFlags...> ) {
121 static_assert(
122 json_details::is_string_view_like_v<String>,
123 "String type must have a be a contiguous range of Characters" );
124 daw_json_ensure( std::size( json_data ) != 0,
125 ErrorReason::EmptyJSONDocument );
126
127 using json_member = json_details::json_deduced_type<JsonMember>;
128
129 static_assert(
130 json_details::has_unnamed_default_type_mapping_v<JsonMember>,
131 "Missing specialization of daw::json::json_data_contract for class "
132 "mapping or specialization of daw::json::json_link_basic_type_map" );
133
134 auto f = daw::not_null<char const *>( std::data( json_data ) );
135 auto l = daw::not_null<char const *>( daw::data_end( json_data ) );
136 Allocator a = alloc;
137
138 using ParsePolicy =
139 BasicParsePolicy<options::parse_flags_t<PolicyFlags...>::value>;
140
143 using ParseState = json_details::apply_zstring_policy_option_t<
144 ParsePolicy,
145 String,
146 options::ZeroTerminatedString::yes>;
147
148 auto parse_state = ParseState::with_allocator( f.get( ), l.get( ), a );
149 if constexpr( ParseState::must_verify_end_of_data_is_valid ) {
150 auto result =
151 json_details::parse_value<json_member,
152 KnownBounds,
153 json_member::expected_type>( parse_state );
154 parse_state.trim_left( );
156 parse_state.empty( ), ErrorReason::InvalidEndOfValue, parse_state );
157 return result;
158 } else {
159 return json_details::
160 parse_value<json_member, KnownBounds, json_member::expected_type>(
161 parse_state );
162 }
163 }
164
173 template<typename JsonMember, bool KnownBounds, typename String,
174 typename Allocator>
175 [[nodiscard]] constexpr auto from_json_alloc( String &&json_data,
176 Allocator const &alloc ) {
177 static_assert(
178 json_details::is_string_view_like_v<String>,
179 "String type must have a be a contiguous range of Characters" );
180 return from_json_alloc<JsonMember, KnownBounds>(
181 DAW_FWD( json_data ), alloc, options::parse_flags<> );
182 }
183
194 template<typename JsonMember, bool KnownBounds, typename String,
195 auto... PolicyFlags>
196 [[nodiscard]] constexpr auto
197 from_json( String &&json_data, std::string_view member_path,
198 options::parse_flags_t<PolicyFlags...> ) {
199 static_assert(
200 json_details::is_string_view_like_v<String>,
201 "String type must have a be a contiguous range of Characters" );
202
203 daw_json_ensure( std::size( json_data ) != 0,
204 ErrorReason::EmptyJSONDocument );
205 daw_json_ensure( std::data( json_data ) != nullptr,
206 ErrorReason::EmptyJSONPath );
207 daw_json_ensure( std::data( member_path ) != nullptr,
208 ErrorReason::EmptyJSONPath );
209
210 using json_member = json_details::json_deduced_type<JsonMember>;
211 static_assert(
212 json_details::has_unnamed_default_type_mapping_v<JsonMember>,
213 "Missing specialization of daw::json::json_data_contract for class "
214 "mapping or specialization of daw::json::json_link_basic_type_map" );
215
216 using ParsePolicy =
217 BasicParsePolicy<options::parse_flags_t<PolicyFlags...>::value>;
218
221 using policy_zstring_t = json_details::apply_zstring_policy_option_t<
222 ParsePolicy,
223 String,
224 options::ZeroTerminatedString::yes>;
225
226 using ParseState =
227 daw::conditional_t<policy_zstring_t::is_default_parse_policy,
229 policy_zstring_t>;
230 auto first = std::data( json_data );
231 auto last = daw::data_end( json_data );
232 if( first != last and last[-1] == 0 ) {
233 --last;
234 }
235 auto jv = basic_json_value( ParseState( first, last ) );
236 jv = jv.find_member( member_path );
237
238 if constexpr( json_details::is_json_nullable_v<json_member> ) {
239 if( not jv ) {
240 return json_details::construct_nullable_empty<
241 json_details::json_constructor_t<json_member>>( );
242 }
243 } else {
244 daw_json_ensure( jv, ErrorReason::JSONPathNotFound );
245 }
246 auto parse_state = jv.get_raw_state( );
247 if constexpr( ParseState::must_verify_end_of_data_is_valid ) {
248 auto result =
249 json_details::parse_value<json_member,
250 KnownBounds,
251 json_member::expected_type>( parse_state );
252 parse_state.trim_left( );
254 parse_state.empty( ), ErrorReason::InvalidEndOfValue, parse_state );
255 return result;
256 } else {
257 return json_details::
258 parse_value<json_member, KnownBounds, json_member::expected_type>(
259 parse_state );
260 }
261 }
262
273 template<typename JsonMember, bool KnownBounds, typename String>
274 [[nodiscard]] constexpr auto from_json( String &&json_data,
275 std::string_view member_path ) {
276 static_assert(
277 json_details::is_string_view_like_v<String>,
278 "String type must have a be a contiguous range of Characters" );
279
280 return from_json<JsonMember, KnownBounds>(
281 DAW_FWD( json_data ), member_path, options::parse_flags<> );
282 }
283
294 template<typename JsonMember, bool KnownBounds, typename String,
295 typename Allocator, auto... PolicyFlags>
296 [[nodiscard]] constexpr auto
297 from_json_alloc( String &&json_data, std::string_view member_path,
298 Allocator const &alloc,
299 options::parse_flags_t<PolicyFlags...> ) {
300
301 static_assert(
302 json_details::is_string_view_like_v<String>,
303 "String type must have a be a contiguous range of Characters" );
304 daw_json_ensure( std::size( json_data ) != 0,
305 ErrorReason::EmptyJSONDocument );
306 daw_json_ensure( std::data( json_data ) != nullptr,
307 ErrorReason::EmptyJSONDocument );
308 daw_json_ensure( std::data( member_path ) != nullptr,
309 ErrorReason::EmptyJSONPath );
310
311 using json_member = json_details::json_deduced_type<JsonMember>;
312 static_assert(
313 json_details::has_unnamed_default_type_mapping_v<JsonMember>,
314 "Missing specialization of daw::json::json_data_contract for class "
315 "mapping or specialization of daw::json::json_link_basic_type_map" );
316
317 using ParsePolicy =
318 BasicParsePolicy<options::parse_flags_t<PolicyFlags...>::value>;
319
322 using ParseState = json_details::apply_zstring_policy_option_t<
323 ParsePolicy,
324 String,
325 options::ZeroTerminatedString::yes>;
326
327 auto first = std::data( json_data );
328 auto last = daw::data_end( json_data );
329 if( first != last and last[-1] == 0 ) {
330 --last;
331 }
332 auto jv = basic_json_value(
333 ParseState( first, last, first, last ).with_allocator( alloc ) );
334 jv = jv.find_member( member_path );
335
336 if constexpr( json_details::is_json_nullable_v<json_member> ) {
337 if( not jv ) {
338 return json_details::construct_nullable_empty<
339 json_details::json_constructor_t<json_member>>( );
340 }
341 } else {
342 daw_json_ensure( jv, ErrorReason::JSONPathNotFound );
343 }
344 auto parse_state = jv.get_raw_state( );
345 if constexpr( ParseState::must_verify_end_of_data_is_valid ) {
346 auto result =
347 json_details::parse_value<json_member,
348 KnownBounds,
349 json_member::expected_type>( parse_state );
350 parse_state.trim_left( );
352 parse_state.empty( ), ErrorReason::InvalidEndOfValue, parse_state );
353 return result;
354 } else {
355 return json_details::
356 parse_value<json_member, KnownBounds, json_member::expected_type>(
357 parse_state );
358 }
359 }
360
371 template<typename JsonMember, bool KnownBounds, typename String,
372 typename Allocator>
373 [[nodiscard]] constexpr auto from_json_alloc( String &&json_data,
374 std::string_view member_path,
375 Allocator const &alloc ) {
376 static_assert(
377 json_details::is_string_view_like_v<String>,
378 "String type must have a be a contiguous range of Characters" );
379
380 return from_json_alloc<JsonMember, KnownBounds>(
381 DAW_FWD( json_data ), member_path, alloc, options::parse_flags<> );
382 }
383
391 template<typename JsonMember, bool KnownBounds, json_options_t P,
392 typename Allocator, auto... PolicyFlags>
393 [[nodiscard]] constexpr auto
395 options::parse_flags_t<PolicyFlags...> ) {
396 using json_member = json_details::json_deduced_type<JsonMember>;
397 static_assert(
398 json_details::has_unnamed_default_type_mapping_v<JsonMember>,
399 "Missing specialization of daw::json::json_data_contract for class "
400 "mapping or specialization of daw::json::json_link_basic_type_map" );
401 using ParsePolicy =
402 typename BasicParsePolicy<P, Allocator>::template SetPolicyOptions<
403 PolicyFlags...>;
404 using ParseState =
405 daw::conditional_t<ParsePolicy::is_default_parse_policy,
407 ParsePolicy>;
408 auto const old_parse_state = value.get_raw_state( );
409 auto parse_state = ParseState( old_parse_state.first,
410 old_parse_state.last,
411 old_parse_state.class_first,
412 old_parse_state.class_last,
413 old_parse_state.get_allocator( ) );
414
415 return json_details::
416 parse_value<json_member, KnownBounds, json_member::expected_type>(
417 parse_state );
418 }
419
427 template<typename JsonMember, bool KnownBounds, json_options_t PolicyFlags,
428 typename Allocator>
429 [[nodiscard]] constexpr auto
431
432 return from_json<JsonMember, KnownBounds>( std::move( value ),
433 options::parse_flags<> );
434 }
435
446 template<typename JsonMember, bool KnownBounds, json_options_t P,
447 typename Allocator, auto... PolicyFlags>
448 [[nodiscard]] constexpr auto
450 std::string_view member_path,
451 options::parse_flags_t<PolicyFlags...> ) {
452 using json_member = json_details::json_deduced_type<JsonMember>;
453 static_assert(
454 json_details::has_unnamed_default_type_mapping_v<JsonMember>,
455 "Missing specialization of daw::json::json_data_contract for class "
456 "mapping or specialization of daw::json::json_link_basic_type_map" );
457 using ParsePolicy =
458 BasicParsePolicy<options::parse_flags_t<PolicyFlags...>::value>;
459 auto const old_parse_state = value.get_raw_state( );
460 using ParseState =
461 daw::conditional_t<ParsePolicy::is_default_parse_policy,
463 ParsePolicy>;
464 auto jv =
465 basic_json_value( ParseState( old_parse_state.first,
466 old_parse_state.last,
467 old_parse_state.class_first,
468 old_parse_state.class_last,
469 old_parse_state.get_allocator( ) ) );
470
471 jv = jv.find_member( member_path );
472
473 if constexpr( json_details::is_json_nullable_v<json_member> ) {
474 if( not jv ) {
475 return json_details::construct_nullable_empty<
476 json_details::json_constructor_t<json_member>>( );
477 }
478 } else {
479 daw_json_ensure( jv, ErrorReason::JSONPathNotFound );
480 }
481 auto parse_state = jv.get_raw_state( );
482 return json_details::
483 parse_value<json_member, KnownBounds, json_member::expected_type>(
484 parse_state );
485 }
486
497 template<typename JsonMember, bool KnownBounds, json_options_t PolicyFlags,
498 typename Allocator>
499 [[nodiscard]] constexpr auto from_json( basic_json_value<PolicyFlags> value,
500 std::string_view member_path ) {
501 return from_json<JsonMember, KnownBounds>(
502 std::move( value ), member_path, options::parse_flags<> );
503 }
504
515 template<typename JsonElement, typename Container, typename Constructor,
516 bool KnownBounds, typename String, auto... PolicyFlags>
517 [[nodiscard]] constexpr Container
518 from_json_array( String &&json_data,
519 options::parse_flags_t<PolicyFlags...> ) {
520 static_assert(
521 json_details::is_string_view_like_v<String>,
522 "String type must have a be a contiguous range of Characters" );
523
524 daw_json_ensure( std::size( json_data ) != 0,
525 ErrorReason::EmptyJSONDocument );
526 daw_json_ensure( std::data( json_data ) != nullptr,
527 ErrorReason::EmptyJSONPath );
528 static_assert(
529 json_details::has_unnamed_default_type_mapping_v<JsonElement>,
530 "Missing specialization of daw::json::json_data_contract for class "
531 "mapping or specialization of daw::json::json_link_basic_type_map" );
532 using element_type = json_details::json_deduced_type<JsonElement>;
533 static_assert( not std::is_same_v<element_type, void>,
534 "Unknown JsonElement type." );
535
536 using parser_t =
537 json_base::json_array<JsonElement, Container, Constructor>;
538
539 using ParsePolicy =
540 BasicParsePolicy<options::parse_flags_t<PolicyFlags...>::value>;
541
544 using policy_zstring_t = json_details::apply_zstring_policy_option_t<
545 ParsePolicy,
546 String,
547 options::ZeroTerminatedString::yes>;
548
549 using ParseState =
550 daw::conditional_t<policy_zstring_t::is_default_parse_policy,
552 policy_zstring_t>;
553 auto parse_state =
554 ParseState{ std::data( json_data ), daw::data_end( json_data ) };
555
556 parse_state.trim_left_unchecked( );
557#if defined( DAW_JSON_BUGFIX_FROM_JSON_001 )
558 daw_json_ensure( parse_state.is_opening_bracket_checked( ),
559 ErrorReason::InvalidArrayStart,
560 parse_state );
561#else
562 daw_json_assert_weak( parse_state.is_opening_bracket_checked( ),
563 ErrorReason::InvalidArrayStart,
564 parse_state );
565#endif
566 if constexpr( ParseState::must_verify_end_of_data_is_valid ) {
567 auto result =
568 json_details::parse_value_array<parser_t, KnownBounds>( parse_state );
569 parse_state.trim_left( );
571 parse_state.empty( ), ErrorReason::InvalidEndOfValue, parse_state );
572 return result;
573 } else {
574 return json_details::parse_value_array<parser_t, KnownBounds>(
575 parse_state );
576 }
577 }
578
589 template<typename JsonElement, typename Container, typename Constructor,
590 bool KnownBounds, typename String>
591 [[nodiscard]] constexpr Container from_json_array( String &&json_data ) {
592 static_assert(
593 json_details::is_string_view_like_v<String>,
594 "String type must have a be a contiguous range of Characters" );
595 return from_json_array<JsonElement, Container, Constructor, KnownBounds>(
596 DAW_FWD( json_data ), options::parse_flags<> );
597 }
598
612 template<typename JsonElement, typename Container, typename Constructor,
613 bool KnownBounds, typename String, auto... PolicyFlags>
614 [[nodiscard]] constexpr Container
615 from_json_array( String &&json_data, std::string_view member_path,
616 options::parse_flags_t<PolicyFlags...> ) {
617 static_assert(
618 json_details::is_string_view_like_v<String>,
619 "String type must have a be a contiguous range of Characters" );
620
621 daw_json_ensure( std::size( json_data ) != 0,
622 ErrorReason::EmptyJSONDocument );
623 daw_json_ensure( std::data( json_data ) != nullptr,
624 ErrorReason::EmptyJSONPath );
625 daw_json_ensure( std::data( member_path ) != nullptr,
626 ErrorReason::EmptyJSONPath );
627 static_assert(
628 json_details::has_unnamed_default_type_mapping_v<JsonElement>,
629 "Missing specialization of daw::json::json_data_contract for class "
630 "mapping or specialization of daw::json::json_link_basic_type_map" );
631 using element_type = json_details::json_deduced_type<JsonElement>;
632 static_assert( not std::is_same_v<element_type, void>,
633 "Unknown JsonElement type." );
634
635 using parser_t =
636 json_base::json_array<JsonElement, Container, Constructor>;
637
638 using ParsePolicy =
639 BasicParsePolicy<options::parse_flags_t<PolicyFlags...>::value>;
640
643 using policy_zstring_t = json_details::apply_zstring_policy_option_t<
644 ParsePolicy,
645 String,
646 options::ZeroTerminatedString::yes>;
647
648 using ParseState =
649 daw::conditional_t<policy_zstring_t::is_default_parse_policy,
651 policy_zstring_t>;
652 auto first = std::data( json_data );
653 auto last = daw::data_end( json_data );
654 if( first != last and last[-1] == 0 ) {
655 --last;
656 }
657 auto jv = basic_json_value( ParseState( first, last ) );
658 jv = jv.find_member( member_path );
659
660 if constexpr( json_details::is_json_nullable_v<parser_t> ) {
661 if( not jv ) {
662 return json_details::construct_nullable_empty<
663 json_details::json_constructor_t<parser_t>>( );
664 }
665 } else {
666 daw_json_ensure( jv, ErrorReason::JSONPathNotFound );
667 }
668 auto parse_state = jv.get_raw_state( );
669 parse_state.trim_left_unchecked( );
670#if defined( DAW_JSON_BUGFIX_FROM_JSON_001 )
671 daw_json_ensure( parse_state.is_opening_bracket_checked( ),
672 ErrorReason::InvalidArrayStart,
673 parse_state );
674#else
675 daw_json_assert_weak( parse_state.is_opening_bracket_checked( ),
676 ErrorReason::InvalidArrayStart,
677 parse_state );
678#endif
679 if constexpr( ParseState::must_verify_end_of_data_is_valid ) {
680 auto result =
681 json_details::parse_value_array<parser_t, KnownBounds>( parse_state );
682 parse_state.trim_left( );
684 parse_state.empty( ), ErrorReason::InvalidEndOfValue, parse_state );
685 return result;
686 } else {
687 return json_details::parse_value_array<parser_t, KnownBounds>(
688 parse_state );
689 }
690 }
691
705 template<typename JsonElement, typename Container, typename Constructor,
706 bool KnownBounds, typename String>
707 [[nodiscard]] constexpr Container
708 from_json_array( String &&json_data, std::string_view member_path ) {
709 static_assert(
710 json_details::is_string_view_like_v<String>,
711 "String type must have a be a contiguous range of Characters" );
712
713 return from_json_array<JsonElement, Container, Constructor, KnownBounds>(
714 DAW_FWD( json_data ), member_path, options::parse_flags<> );
715 }
716 } // namespace DAW_JSON_VER
717} // 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.
constexpr ParseState get_raw_state() const
Get a copy of the underlying parse state.
#define DAW_JSON_VER
The version string used in namespace definitions. Must be a valid namespace name.
Definition version.h:20