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 =
63 daw::not_null<typename ParsePolicy::iterator>( std::data( json_data ) );
64 auto last = daw::not_null<typename ParsePolicy::iterator>(
65 daw::data_end( json_data ) );
66 if( first != last and last[-1] == 0 ) {
67 --last;
68 }
69
70 using ParseState =
71 daw::conditional_t<policy_zstring_t::is_default_parse_policy,
73 policy_zstring_t>;
74
75 auto parse_state = ParseState( first.get( ), last.get( ) );
76
77 if constexpr( ParseState::must_verify_end_of_data_is_valid ) {
78 auto result =
79 json_details::parse_value<json_member,
80 KnownBounds,
81 json_member::expected_type>( parse_state );
82 parse_state.trim_left( );
84 parse_state.empty( ), ErrorReason::InvalidEndOfValue, parse_state );
85 return result;
86 } else {
87 return json_details::
88 parse_value<json_member, KnownBounds, json_member::expected_type>(
89 parse_state );
90 }
91 }
92
101 template<typename JsonMember, bool KnownBounds, typename String>
102 [[nodiscard]] constexpr auto from_json( String &&json_data ) {
103 static_assert(
104 json_details::is_string_view_like_v<String>,
105 "String type must have a be a contiguous range of Characters" );
106 return from_json<JsonMember, KnownBounds>( DAW_FWD( json_data ),
107 options::parse_flags<> );
108 }
109
113 template<typename JsonMember, bool KnownBounds, typename String,
114 auto... PolicyFlags>
115 [[nodiscard]] constexpr auto
116 from_json_insitu( String &&json_data,
117 options::parse_flags_t<PolicyFlags...> ) {
118 static_assert( std::is_same_v<decltype( std::data( json_data ) ), char *>,
119 "from_json_insitu requires a mutable character buffer" );
120 return from_json<JsonMember, KnownBounds>(
121 DAW_FWD( json_data ),
122 options::parse_flags<PolicyFlags...,
123 options::AllowStringMutation::yes> );
124 }
125
126 template<typename JsonMember, bool KnownBounds, typename String>
127 [[nodiscard]] constexpr auto from_json_insitu( String &&json_data ) {
128 return from_json_insitu<JsonMember, KnownBounds>(
129 DAW_FWD( json_data ), options::parse_flags<> );
130 }
131
140 template<typename JsonMember, bool KnownBounds, typename String,
141 typename Allocator, auto... PolicyFlags>
142 [[nodiscard]] constexpr auto
143 from_json_alloc( String &&json_data, Allocator const &alloc,
144 options::parse_flags_t<PolicyFlags...> ) {
145 static_assert(
146 json_details::is_string_view_like_v<String>,
147 "String type must have a be a contiguous range of Characters" );
148 daw_json_ensure( std::size( json_data ) != 0,
149 ErrorReason::EmptyJSONDocument );
150
151 using json_member = json_details::json_deduced_type<JsonMember>;
152
153 static_assert(
154 json_details::has_unnamed_default_type_mapping_v<JsonMember>,
155 "Missing specialization of daw::json::json_data_contract for class "
156 "mapping or specialization of daw::json::json_link_basic_type_map" );
157
158 auto f = daw::not_null<char const *>( std::data( json_data ) );
159 auto l = daw::not_null<char const *>( daw::data_end( json_data ) );
160 Allocator a = alloc;
161
162 using ParsePolicy =
163 BasicParsePolicy<options::parse_flags_t<PolicyFlags...>::value>;
164
167 using ParseState = json_details::apply_zstring_policy_option_t<
168 ParsePolicy,
169 String,
170 options::ZeroTerminatedString::yes>;
171
172 auto parse_state = ParseState::with_allocator( f.get( ), l.get( ), a );
173 if constexpr( ParseState::must_verify_end_of_data_is_valid ) {
174 auto result =
175 json_details::parse_value<json_member,
176 KnownBounds,
177 json_member::expected_type>( parse_state );
178 parse_state.trim_left( );
180 parse_state.empty( ), ErrorReason::InvalidEndOfValue, parse_state );
181 return result;
182 } else {
183 return json_details::
184 parse_value<json_member, KnownBounds, json_member::expected_type>(
185 parse_state );
186 }
187 }
188
197 template<typename JsonMember, bool KnownBounds, typename String,
198 typename Allocator>
199 [[nodiscard]] constexpr auto from_json_alloc( String &&json_data,
200 Allocator const &alloc ) {
201 static_assert(
202 json_details::is_string_view_like_v<String>,
203 "String type must have a be a contiguous range of Characters" );
204 return from_json_alloc<JsonMember, KnownBounds>(
205 DAW_FWD( json_data ), alloc, options::parse_flags<> );
206 }
207
218 template<typename JsonMember, bool KnownBounds, typename String,
219 auto... PolicyFlags>
220 [[nodiscard]] constexpr auto
221 from_json( String &&json_data, std::string_view member_path,
222 options::parse_flags_t<PolicyFlags...> ) {
223 static_assert(
224 json_details::is_string_view_like_v<String>,
225 "String type must have a be a contiguous range of Characters" );
226
227 daw_json_ensure( std::size( json_data ) != 0,
228 ErrorReason::EmptyJSONDocument );
229 daw_json_ensure( std::data( json_data ) != nullptr,
230 ErrorReason::EmptyJSONPath );
231 daw_json_ensure( std::data( member_path ) != nullptr,
232 ErrorReason::EmptyJSONPath );
233
234 using json_member = json_details::json_deduced_type<JsonMember>;
235 static_assert(
236 json_details::has_unnamed_default_type_mapping_v<JsonMember>,
237 "Missing specialization of daw::json::json_data_contract for class "
238 "mapping or specialization of daw::json::json_link_basic_type_map" );
239
240 using ParsePolicy =
241 BasicParsePolicy<options::parse_flags_t<PolicyFlags...>::value>;
242
245 using policy_zstring_t = json_details::apply_zstring_policy_option_t<
246 ParsePolicy,
247 String,
248 options::ZeroTerminatedString::yes>;
249
250 using ParseState =
251 daw::conditional_t<policy_zstring_t::is_default_parse_policy,
253 policy_zstring_t>;
254 auto first = std::data( json_data );
255 auto last = daw::data_end( json_data );
256 if( first != last and last[-1] == 0 ) {
257 --last;
258 }
259 auto jv = basic_json_value( ParseState( first, last ) );
260 jv = jv.find_member( member_path );
261
262 if constexpr( json_details::is_json_nullable_v<json_member> ) {
263 if( not jv ) {
264 return json_details::construct_nullable_empty<
265 json_details::json_constructor_t<json_member>>( );
266 }
267 } else {
268 daw_json_ensure( jv, ErrorReason::JSONPathNotFound );
269 }
270 auto parse_state = jv.get_raw_state( );
271 if constexpr( ParseState::must_verify_end_of_data_is_valid ) {
272 auto result =
273 json_details::parse_value<json_member,
274 KnownBounds,
275 json_member::expected_type>( parse_state );
276 parse_state.trim_left( );
278 parse_state.empty( ), ErrorReason::InvalidEndOfValue, parse_state );
279 return result;
280 } else {
281 return json_details::
282 parse_value<json_member, KnownBounds, json_member::expected_type>(
283 parse_state );
284 }
285 }
286
297 template<typename JsonMember, bool KnownBounds, typename String>
298 [[nodiscard]] constexpr auto from_json( String &&json_data,
299 std::string_view member_path ) {
300 static_assert(
301 json_details::is_string_view_like_v<String>,
302 "String type must have a be a contiguous range of Characters" );
303
304 return from_json<JsonMember, KnownBounds>(
305 DAW_FWD( json_data ), member_path, options::parse_flags<> );
306 }
307
318 template<typename JsonMember, bool KnownBounds, typename String,
319 typename Allocator, auto... PolicyFlags>
320 [[nodiscard]] constexpr auto
321 from_json_alloc( String &&json_data, std::string_view member_path,
322 Allocator const &alloc,
323 options::parse_flags_t<PolicyFlags...> ) {
324
325 static_assert(
326 json_details::is_string_view_like_v<String>,
327 "String type must have a be a contiguous range of Characters" );
328 daw_json_ensure( std::size( json_data ) != 0,
329 ErrorReason::EmptyJSONDocument );
330 daw_json_ensure( std::data( json_data ) != nullptr,
331 ErrorReason::EmptyJSONDocument );
332 daw_json_ensure( std::data( member_path ) != nullptr,
333 ErrorReason::EmptyJSONPath );
334
335 using json_member = json_details::json_deduced_type<JsonMember>;
336 static_assert(
337 json_details::has_unnamed_default_type_mapping_v<JsonMember>,
338 "Missing specialization of daw::json::json_data_contract for class "
339 "mapping or specialization of daw::json::json_link_basic_type_map" );
340
341 using ParsePolicy =
342 BasicParsePolicy<options::parse_flags_t<PolicyFlags...>::value>;
343
346 using ParseState = json_details::apply_zstring_policy_option_t<
347 ParsePolicy,
348 String,
349 options::ZeroTerminatedString::yes>;
350
351 auto first = std::data( json_data );
352 auto last = daw::data_end( json_data );
353 if( first != last and last[-1] == 0 ) {
354 --last;
355 }
356 auto jv = basic_json_value(
357 ParseState( first, last, first, last ).with_allocator( alloc ) );
358 jv = jv.find_member( member_path );
359
360 if constexpr( json_details::is_json_nullable_v<json_member> ) {
361 if( not jv ) {
362 return json_details::construct_nullable_empty<
363 json_details::json_constructor_t<json_member>>( );
364 }
365 } else {
366 daw_json_ensure( jv, ErrorReason::JSONPathNotFound );
367 }
368 auto parse_state = jv.get_raw_state( );
369 if constexpr( ParseState::must_verify_end_of_data_is_valid ) {
370 auto result =
371 json_details::parse_value<json_member,
372 KnownBounds,
373 json_member::expected_type>( parse_state );
374 parse_state.trim_left( );
376 parse_state.empty( ), ErrorReason::InvalidEndOfValue, parse_state );
377 return result;
378 } else {
379 return json_details::
380 parse_value<json_member, KnownBounds, json_member::expected_type>(
381 parse_state );
382 }
383 }
384
395 template<typename JsonMember, bool KnownBounds, typename String,
396 typename Allocator>
397 [[nodiscard]] constexpr auto from_json_alloc( String &&json_data,
398 std::string_view member_path,
399 Allocator const &alloc ) {
400 static_assert(
401 json_details::is_string_view_like_v<String>,
402 "String type must have a be a contiguous range of Characters" );
403
404 return from_json_alloc<JsonMember, KnownBounds>(
405 DAW_FWD( json_data ), member_path, alloc, options::parse_flags<> );
406 }
407
415 template<typename JsonMember, bool KnownBounds, json_options_t P,
416 typename Allocator, auto... PolicyFlags>
417 [[nodiscard]] constexpr auto
419 options::parse_flags_t<PolicyFlags...> ) {
420 using json_member = json_details::json_deduced_type<JsonMember>;
421 static_assert(
422 json_details::has_unnamed_default_type_mapping_v<JsonMember>,
423 "Missing specialization of daw::json::json_data_contract for class "
424 "mapping or specialization of daw::json::json_link_basic_type_map" );
425 using ParsePolicy =
426 typename BasicParsePolicy<P, Allocator>::template SetPolicyOptions<
427 PolicyFlags...>;
428 using ParseState =
429 daw::conditional_t<ParsePolicy::is_default_parse_policy,
431 ParsePolicy>;
432 auto const old_parse_state = value.get_raw_state( );
433 auto parse_state = ParseState( old_parse_state.first,
434 old_parse_state.last,
435 old_parse_state.class_first,
436 old_parse_state.class_last,
437 old_parse_state.get_allocator( ) );
438
439 return json_details::
440 parse_value<json_member, KnownBounds, json_member::expected_type>(
441 parse_state );
442 }
443
451 template<typename JsonMember, bool KnownBounds, json_options_t PolicyFlags,
452 typename Allocator>
453 [[nodiscard]] constexpr auto
455
456 return from_json<JsonMember, KnownBounds>( std::move( value ),
457 options::parse_flags<> );
458 }
459
470 template<typename JsonMember, bool KnownBounds, json_options_t P,
471 typename Allocator, auto... PolicyFlags>
472 [[nodiscard]] constexpr auto
474 std::string_view member_path,
475 options::parse_flags_t<PolicyFlags...> ) {
476 using json_member = json_details::json_deduced_type<JsonMember>;
477 static_assert(
478 json_details::has_unnamed_default_type_mapping_v<JsonMember>,
479 "Missing specialization of daw::json::json_data_contract for class "
480 "mapping or specialization of daw::json::json_link_basic_type_map" );
481 using ParsePolicy =
482 BasicParsePolicy<options::parse_flags_t<PolicyFlags...>::value>;
483 auto const old_parse_state = value.get_raw_state( );
484 using ParseState =
485 daw::conditional_t<ParsePolicy::is_default_parse_policy,
487 ParsePolicy>;
488 auto jv =
489 basic_json_value( ParseState( old_parse_state.first,
490 old_parse_state.last,
491 old_parse_state.class_first,
492 old_parse_state.class_last,
493 old_parse_state.get_allocator( ) ) );
494
495 jv = jv.find_member( member_path );
496
497 if constexpr( json_details::is_json_nullable_v<json_member> ) {
498 if( not jv ) {
499 return json_details::construct_nullable_empty<
500 json_details::json_constructor_t<json_member>>( );
501 }
502 } else {
503 daw_json_ensure( jv, ErrorReason::JSONPathNotFound );
504 }
505 auto parse_state = jv.get_raw_state( );
506 return json_details::
507 parse_value<json_member, KnownBounds, json_member::expected_type>(
508 parse_state );
509 }
510
521 template<typename JsonMember, bool KnownBounds, json_options_t PolicyFlags,
522 typename Allocator>
523 [[nodiscard]] constexpr auto from_json( basic_json_value<PolicyFlags> value,
524 std::string_view member_path ) {
525 return from_json<JsonMember, KnownBounds>(
526 std::move( value ), member_path, options::parse_flags<> );
527 }
528
539 template<typename JsonElement, typename Container, typename Constructor,
540 bool KnownBounds, typename String, auto... PolicyFlags>
541 [[nodiscard]] constexpr Container
542 from_json_array( String &&json_data,
543 options::parse_flags_t<PolicyFlags...> ) {
544 static_assert(
545 json_details::is_string_view_like_v<String>,
546 "String type must have a be a contiguous range of Characters" );
547
548 daw_json_ensure( std::size( json_data ) != 0,
549 ErrorReason::EmptyJSONDocument );
550 daw_json_ensure( std::data( json_data ) != nullptr,
551 ErrorReason::EmptyJSONPath );
552 static_assert(
553 json_details::has_unnamed_default_type_mapping_v<JsonElement>,
554 "Missing specialization of daw::json::json_data_contract for class "
555 "mapping or specialization of daw::json::json_link_basic_type_map" );
556 using element_type = json_details::json_deduced_type<JsonElement>;
557 static_assert( not std::is_same_v<element_type, void>,
558 "Unknown JsonElement type." );
559
560 using parser_t =
561 json_base::json_array<JsonElement, Container, Constructor>;
562
563 using ParsePolicy =
564 BasicParsePolicy<options::parse_flags_t<PolicyFlags...>::value>;
565
568 using policy_zstring_t = json_details::apply_zstring_policy_option_t<
569 ParsePolicy,
570 String,
571 options::ZeroTerminatedString::yes>;
572
573 using ParseState =
574 daw::conditional_t<policy_zstring_t::is_default_parse_policy,
576 policy_zstring_t>;
577 auto parse_state =
578 ParseState{ std::data( json_data ), daw::data_end( json_data ) };
579
580 parse_state.trim_left_unchecked( );
581#if defined( DAW_JSON_BUGFIX_FROM_JSON_001 )
582 daw_json_ensure( parse_state.is_opening_bracket_checked( ),
583 ErrorReason::InvalidArrayStart,
584 parse_state );
585#else
586 daw_json_assert_weak( parse_state.is_opening_bracket_checked( ),
587 ErrorReason::InvalidArrayStart,
588 parse_state );
589#endif
590 if constexpr( ParseState::must_verify_end_of_data_is_valid ) {
591 auto result =
592 json_details::parse_value_array<parser_t, KnownBounds>( parse_state );
593 parse_state.trim_left( );
595 parse_state.empty( ), ErrorReason::InvalidEndOfValue, parse_state );
596 return result;
597 } else {
598 return json_details::parse_value_array<parser_t, KnownBounds>(
599 parse_state );
600 }
601 }
602
613 template<typename JsonElement, typename Container, typename Constructor,
614 bool KnownBounds, typename String>
615 [[nodiscard]] constexpr Container from_json_array( String &&json_data ) {
616 static_assert(
617 json_details::is_string_view_like_v<String>,
618 "String type must have a be a contiguous range of Characters" );
619 return from_json_array<JsonElement, Container, Constructor, KnownBounds>(
620 DAW_FWD( json_data ), options::parse_flags<> );
621 }
622
636 template<typename JsonElement, typename Container, typename Constructor,
637 bool KnownBounds, typename String, auto... PolicyFlags>
638 [[nodiscard]] constexpr Container
639 from_json_array( String &&json_data, std::string_view member_path,
640 options::parse_flags_t<PolicyFlags...> ) {
641 static_assert(
642 json_details::is_string_view_like_v<String>,
643 "String type must have a be a contiguous range of Characters" );
644
645 daw_json_ensure( std::size( json_data ) != 0,
646 ErrorReason::EmptyJSONDocument );
647 daw_json_ensure( std::data( json_data ) != nullptr,
648 ErrorReason::EmptyJSONPath );
649 daw_json_ensure( std::data( member_path ) != nullptr,
650 ErrorReason::EmptyJSONPath );
651 static_assert(
652 json_details::has_unnamed_default_type_mapping_v<JsonElement>,
653 "Missing specialization of daw::json::json_data_contract for class "
654 "mapping or specialization of daw::json::json_link_basic_type_map" );
655 using element_type = json_details::json_deduced_type<JsonElement>;
656 static_assert( not std::is_same_v<element_type, void>,
657 "Unknown JsonElement type." );
658
659 using parser_t =
660 json_base::json_array<JsonElement, Container, Constructor>;
661
662 using ParsePolicy =
663 BasicParsePolicy<options::parse_flags_t<PolicyFlags...>::value>;
664
667 using policy_zstring_t = json_details::apply_zstring_policy_option_t<
668 ParsePolicy,
669 String,
670 options::ZeroTerminatedString::yes>;
671
672 using ParseState =
673 daw::conditional_t<policy_zstring_t::is_default_parse_policy,
675 policy_zstring_t>;
676 auto first = std::data( json_data );
677 auto last = daw::data_end( json_data );
678 if( first != last and last[-1] == 0 ) {
679 --last;
680 }
681 auto jv = basic_json_value( ParseState( first, last ) );
682 jv = jv.find_member( member_path );
683
684 if constexpr( json_details::is_json_nullable_v<parser_t> ) {
685 if( not jv ) {
686 return json_details::construct_nullable_empty<
687 json_details::json_constructor_t<parser_t>>( );
688 }
689 } else {
690 daw_json_ensure( jv, ErrorReason::JSONPathNotFound );
691 }
692 auto parse_state = jv.get_raw_state( );
693 parse_state.trim_left_unchecked( );
694#if defined( DAW_JSON_BUGFIX_FROM_JSON_001 )
695 daw_json_ensure( parse_state.is_opening_bracket_checked( ),
696 ErrorReason::InvalidArrayStart,
697 parse_state );
698#else
699 daw_json_assert_weak( parse_state.is_opening_bracket_checked( ),
700 ErrorReason::InvalidArrayStart,
701 parse_state );
702#endif
703 if constexpr( ParseState::must_verify_end_of_data_is_valid ) {
704 auto result =
705 json_details::parse_value_array<parser_t, KnownBounds>( parse_state );
706 parse_state.trim_left( );
708 parse_state.empty( ), ErrorReason::InvalidEndOfValue, parse_state );
709 return result;
710 } else {
711 return json_details::parse_value_array<parser_t, KnownBounds>(
712 parse_state );
713 }
714 }
715
729 template<typename JsonElement, typename Container, typename Constructor,
730 bool KnownBounds, typename String>
731 [[nodiscard]] constexpr Container
732 from_json_array( String &&json_data, std::string_view member_path ) {
733 static_assert(
734 json_details::is_string_view_like_v<String>,
735 "String type must have a be a contiguous range of Characters" );
736
737 return from_json_array<JsonElement, Container, Constructor, KnownBounds>(
738 DAW_FWD( json_data ), member_path, options::parse_flags<> );
739 }
740 } // namespace DAW_JSON_VER
741} // 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.
constexpr auto from_json_insitu(String &&json_data, options::parse_flags_t< PolicyFlags... >)
Parse a writable JSON buffer with string mutation enabled. The buffer must remain alive and at a stab...
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