ไลบรารี JSON Link มีประสิทธิภาพสูง ไม่มีการจัดสรร ไลบรารี C++ JSON รองรับ:
ไลบรารีสนับสนุนโหมดการแยกวิเคราะห์อื่นๆ ที่สามารถผสมกันได้
json_array_iterator
หรือ json_array_range
json_value
ที่อนุญาตการวนซ้ำ/การแยกวิเคราะห์เอกสารแบบ Lazyคุณสมบัติเด่นอื่นๆ ได้แก่:
boost::multiprecision::cpp_int
หรือ GNU BigNum/Rational mpq_t
ห้องสมุดใช้ใบอนุญาต BSL
เมื่อทราบโครงสร้างของเอกสาร JSON การแยกวิเคราะห์จะเป็นดังนี้:
MyThing thing = daw::json::from_json<MyThing>( json_string );
หรือสำหรับเอกสารอาเรย์โดยที่รากของเอกสารเป็นอาเรย์จะมีเมธอดตัวช่วยที่ช่วยให้ง่ายขึ้นและสามารถแยกวิเคราะห์ได้ดังนี้
std::vector<MyThing> things = daw::json::from_json_array<MyThing>( json_string2 );
หากไม่ทราบโครงสร้างของเอกสาร JSON เราสามารถสร้าง json_value
ที่ทำหน้าที่เป็นมุมมองและอนุญาตให้วนซ้ำและดึงการแยกวิเคราะห์ตามความต้องการ ต่อไปนี้เป็นตัวอย่างของการเปิด json_value
จากข้อมูล JSON:
json_value val = daw::json::json_value( json_string );
เมธอด from_json
และ to_json
ช่วยให้สามารถเข้าถึงความต้องการในการแยกวิเคราะห์และซีเรียลไลซ์ส่วนใหญ่ได้
parser ตามเหตุการณ์ (SAX) สามารถเรียกผ่าน daw::json::json_event_parser
ต้องใช้สองอาร์กิวเมนต์ เอกสาร json และตัวจัดการเหตุการณ์ ตัวจัดการเหตุการณ์สามารถเลือกเข้าร่วมกิจกรรมได้โดยมีสมาชิกคนใดคนหนึ่งต่อไปนี้:
การแม็พคลาสของคุณกับเอกสาร JSON ทำได้โดยการเน้นคุณลักษณะ daw::json::json_data_contract
คลาสที่ถูกแมปไม่จำเป็นต้องถูกแมปอีกครั้งหากเป็นสมาชิกของคลาสที่แมปอื่น ลักษณะมีสองส่วน json_data_contract
ส่วนแรกคือ type
นามแฝงที่ตั้งชื่อประเภทที่แมปสมาชิก JSON กับตัวสร้างคลาสของเรา สิ่งนี้ทำให้จำเป็นต้องเข้าถึงคลาสแบบส่วนตัว โดยสมมติว่าข้อมูลที่เราจะซีเรียลไลซ์นั้นจำเป็นต่อการสร้างคลาสด้วย ตัวอย่างเช่น:
struct Thing {
int a;
int b;
};
โครงสร้างสำหรับ Thing
ต้องใช้จำนวนเต็ม 2 ตัว และหากเรามี JSON ต่อไปนี้:
{
"a" : 42 ,
"b" : 1234
}
เราสามารถทำการ mapping ได้ดังนี้:
namespace daw ::json {
template <>
struct json_data_contract <Thing> {
static constexpr char const a[] = " a " ;
static constexpr char const b[] = " b " ;
using type = json_member_list<
json_number<a, int >,
json_number<b, int >
>;
};
}
สิ่งนี้บอกว่าคลาส JSON ในเอกสารจะมีสมาชิกอย่างน้อยสองตัวคือ "a" และ "b" ซึ่งจะเป็นตัวเลขที่เป็นจำนวนเต็ม พวกเขาจะถูกส่งต่อไปยังตัวสร้างของ Thing
เมื่อ daw::json::from_json<Thing>( json_doc );
ถูกเรียก หรือคลาสอื่นมีการแมปสมาชิก json_class<MemberName, Thing>
ด้านบนนี้เป็นวิธีการแมปชื่อ C++17 ซึ่งใช้ได้กับเวอร์ชัน C++ ในอนาคตด้วย แต่ใน C ++ 20 และใหม่กว่าชื่อสามารถอยู่ในบรรทัดในการแมปเช่น json_number<"a", int>
ข้างต้นคือทั้งหมดที่จำเป็นสำหรับการแยกวิเคราะห์ JSON สำหรับการซีเรียลไลซ์ฟังก์ชันสมาชิกแบบคงที่เป็นสิ่งจำเป็นในลักษณะ จากตัวอย่างก่อนหน้านี้และขยายออกไป เราสามารถทำให้ Thing
เป็นอนุกรมได้ด้วย:
namespace daw ::json {
template <>
struct json_data_contract <Thing> {
static constexpr char const a[] = " a " ;
static constexpr char const b[] = " b " ;
using type = json_member_list<
json_number<a, int >,
json_number<b, int >
>;
};
static auto to_json_data ( Thing const & v ) {
return std::forward_as_tuple ( v. a , v. b );
}
}
ลำดับของสมาชิกที่ส่งคืนเป็นสิ่งทูเปิลต้องตรงกับการแมปใน type
นามแฝงประเภท วิธีนี้ช่วยให้สามารถส่งผลลัพธ์ของวิธีการเข้าถึงได้เช่นกัน หากสมาชิกข้อมูลไม่ได้เป็นแบบสาธารณะ นอกจากนี้คลาส Thing
จะต้องสามารถสร้างได้จาก int, int
ไลบรารีรองรับทั้งคอนสตรัคเตอร์ทั่วไปและ init รวม ( Thing{ int, int }
และ Thing( int, int )
) ใน C++17
to_json_data
ไม่จำเป็นต้องส่งคืนการอ้างอิงถึงสมาชิกออบเจ็กต์ที่มีอยู่ แต่สามารถส่งคืนค่าที่คำนวณได้เช่นกัน ไม่อนุญาตให้มีค่า r ผ่านเนื่องจากมักเป็นเพียงค่าชั่วคราว และอาจส่งผลให้เกิดการดีบักระยะไกลได้ ไลบรารีจะ static_assert ในเรื่องนี้และแนะนำให้รวม <daw/daw_tuple_forward.h>
และการเรียก daw::forward_nonrvalue_as_tuple( ... )
ซึ่งจัดเก็บชั่วคราวและส่งต่อประเภทการอ้างอิงอื่น ๆ parsers ทำงานโดยการสร้างแต่ละอาร์กิวเมนต์ในการเรียกไปยัง Constructor ของคลาส ตัวแยกวิเคราะห์อาร์กิวเมนต์แต่ละตัวสามารถปรับให้เข้ากับสถานการณ์ที่ระบุของข้อมูลได้ (เช่น จุดลอยตัวและจำนวนเต็ม) จากนั้นด้วยลักษณะประเภทของเราที่กำหนดอาร์กิวเมนต์ที่จำเป็นในการสร้างคลาส C++ และลำดับของมัน เราจึงสามารถดูสมาชิกแต่ละคนใน JSON ได้ ตอนนี้เราสร้างค่าด้วยผลลัพธ์ของ parser แต่ละตัว คล้ายกับ T{ parse<0, json_string<"name">>( data ), parse<1, json_number<"age", unsigned>>( data ), parse<json_number<2, "number>>( data )}
สำหรับสมาชิกแต่ละคน สตรีมข้อมูลจะถูกย้ายไปข้างหน้าจนกว่าเราจะพบสมาชิกที่เราต้องแยกวิเคราะห์ โดยจัดเก็บตำแหน่งที่สนใจไว้สำหรับการแยกวิเคราะห์ในภายหลัง json_class<"member_name", Type>
ประเภทการแมป เพื่อให้แต่ละลักษณะการแมปต้องจัดการกับสมาชิกเฉพาะเท่านั้น ไม่ใช่รายละเอียด
ในบริบทที่ไม่มีชื่อ เช่น ค่ารูท องค์ประกอบอาร์เรย์ ประเภทค่าคีย์บางประเภท และรายการองค์ประกอบตัวแปรที่ชื่อจะเป็น no_name
เราสามารถใช้ประเภทข้อมูล C++ ดั้งเดิมบางประเภทแทนประเภทการแมป JSON ซึ่งรวมถึงจำนวนเต็ม จุดลอยตัว บูล std::string, std::string_view คอนเทนเนอร์แบบเชื่อมโยง คอนเทนเนอร์ลำดับ ประเภท Nullable/Optional และคลาสที่แมปไว้ก่อนหน้านี้
ตัวอย่างเช่น เมื่อต้องการแมปอาร์เรย์ของสตริง
template <>
struct daw ::json::json_data_contract<MyType> {
using type = json_member_list<json_array< " member_name " , std::string>>;
};
เราสามารถใช้ vcpkg เพื่อคว้ารีลีสล่าสุดได้ พอร์ตนี้เรียกว่า daw-json-link
find_package ( daw-json-link )
#...
target_link_libraries ( MyTarget daw::daw-json-link )
ไลบรารีเป็นส่วนหัวเท่านั้นและสามารถโคลนได้ พร้อมกับการขึ้นต่อกันสองรายการ ตามด้วยการเพิ่มโฟลเดอร์ include/
ของแต่ละโฟลเดอร์ลงในพาธการรวมของคอมไพเลอร์
หากต้องการใช้ daw_json_link ในโปรเจ็กต์ cmake ของคุณ การเพิ่มสิ่งต่อไปนี้ควรอนุญาตให้ดึงเข้าไปพร้อมกับการอ้างอิง:
include ( FetchContent )
FetchContent_Declare(
daw_json_link
GIT_REPOSITORY https://github.com/beached/daw_json_link
GIT_TAG release
)
FetchContent_MakeAvailable(daw_json_link)
#...
target_link_libraries ( MyTarget daw::daw-json-link )
บนระบบที่มี bash มันจะคล้ายกับระบบอื่นเช่นกัน สามารถติดตั้งสิ่งต่อไปนี้สำหรับระบบได้
git clone https://github.com/beached/daw_json_link
cd daw_json_link
mkdir build
cd build
cmake ..
cmake --install .
สิ่งนี้จะอนุญาตให้ติดตั้ง cmake find_package หรือใช้เป็นส่วนหัวปกติได้ตราบใดที่โฟลเดอร์รวมของคำนำหน้าการติดตั้งนั้นรวมอยู่ในพา ธ รวมของคอมไพเลอร์
ต่อไปนี้จะสร้างและรันการทดสอบ
git clone https://github.com/beached/daw_json_link
cd daw_json_link
mkdir build
cd build
cmake -DDAW_ENABLE_TESTING=On ..
cmake --build .
ctest .
หลังจาก build แล้ว ก็สามารถทดสอบตัวอย่างแต่ละรายการได้เช่นกัน city_test_bin
ต้องการเส้นทางไปยังไฟล์ JSON ของเมือง
./tests/city_test_bin ../test_data/cities.json
โดยทั่วไปลำดับของสมาชิกในโครงสร้างข้อมูลควรตรงกับลำดับของข้อมูล JSON หากเป็นไปได้ parser จะเร็วขึ้นหากไม่ต้องติดตามค่า ค่าที่ไม่บังคับเมื่อไม่มีข้อมูล JSON ก็อาจทำให้การแยกวิเคราะห์ช้าลงเช่นกัน ถ้าเป็นไปได้ให้ส่งเป็นโมฆะ parser ไม่ได้จัดสรร การแยกวิเคราะห์เป็นประเภทข้อมูลอาจอนุญาตให้ใช้ตัวจัดสรรแบบกำหนดเองหรือแบบผสมเนื่องจากโครงสร้างข้อมูลจะทำการจัดสรร ค่าเริ่มต้นสำหรับอาร์เรย์คือการใช้ std::vector และหากไม่ต้องการ คุณจะต้องระบุประเภท
ในปัจจุบัน ไลบรารีไม่ได้ Escape/Escape ชื่อสมาชิกเมื่อทำซีเรียลไลซ์ ซึ่งคาดว่าจะถูกต้องและไม่ได้ใช้ Escape นี่อาจเป็นทางเลือกเพิ่มเติมในอนาคต เนื่องจากมีค่าใช้จ่าย
มีความแตกต่างเล็กน้อยระหว่าง C++17 และ C++20 โดยที่ C++20 อนุญาตสำหรับบางโค้ดที่ไม่มีใน C++17
namespace daw ::json {
template <>
struct json_data_contract <MyType> {
static constexpr char const member_name[] = " memberName " ;
using type = json_member_list<json_number<member_name>>;
};
}
C++ ทั้งสองเวอร์ชันรองรับวิธีนี้ในการตั้งชื่อสมาชิก
เมื่อคอมไพล์ภายในคอมไพเลอร์ C++20 นอกเหนือจากการส่งผ่าน char const *
เช่นเดียวกับใน C++17 แล้ว ชื่อสมาชิกสามารถระบุเป็นตัวอักษรสตริงได้โดยตรง การสนับสนุนคอมไพเลอร์ C++20 ยังเร็วมากและนี่คือมังกร มีปัญหาที่ทราบเกี่ยวกับ g++9.x ในโหมด C++20 และมีการทดสอบกับ g++10/11 เท่านั้น นี่จะเป็นมังกร
namespace daw ::json {
template <>
struct json_data_contract <MyType> {
using type = json_member_list<json_number< " member_name " >>;
};
}
เมื่อประเภทข้อมูลได้รับการแมปกับ json_data_contract
แล้ว ไลบรารีจะมีวิธีการในการแยกวิเคราะห์ JSON ให้กับพวกเขา
MyClass my_class = from_json<MyClass>( json_str );
หรือหากอินพุตเชื่อถือได้ เวอร์ชันที่ตรวจสอบน้อยกว่าก็สามารถทำงานได้เร็วขึ้น
MyClass my_class = from_json<MyClass, options::parse_flags<options::CheckedParseMode::no>>( json_str );
เอกสาร JSON ที่มีอาร์เรย์รูทใช้ฟังก์ชัน from_json_array
เพื่อแยกวิเคราะห์
std::vector<MyClass> my_data = from_json_array<MyClass>( json_str );
หรือหากอินพุตเชื่อถือได้ เวอร์ชันที่ตรวจสอบน้อยกว่าก็สามารถทำงานได้เร็วขึ้น
std::vector<MyClass> my_data = from_json_array<MyClass, std::vector<MyClass>, options::parse_flags<options::CheckedParseMode::no>>( json_str );
json_array_iterator
หากคุณต้องการทำงานจากข้อมูลอาร์เรย์ JSON คุณสามารถรับตัววนซ้ำและใช้อัลกอริทึม std เพื่อวนซ้ำผ่านอาร์เรย์ในข้อมูล JSON สามารถทำได้ผ่าน json_array_iterator
using iterator_t = json_array_iterator<MyClass>;
auto pos = std::find( iterator_t ( json_str ), iterator_t ( ), MyClass( ... ) );
อีกทางหนึ่ง หากอินพุตเชื่อถือได้ คุณสามารถเรียกเวอร์ชันที่ตรวจสอบน้อยกว่าได้
using iterator_t = daw::json::json_array_iterator<MyClass, options::CheckedParseMode::no>;
auto pos = std::find( iterator_t ( json_str ), iterator_t ( ), MyClass( ... ) );
json_value
สำหรับ DOM เช่น api ซึ่งมักใช้กับสิ่งต่างๆ เช่น GUI และการให้โค้ดเมื่อการแมปไม่เพียงพอ เราสามารถใช้ json_value
ได้ สิ่งนี้ใช้ในเครื่องมือ json_to_cpp
auto jv = daw::json::json_value( json_doc );
เราสามารถใช้ JSON Path เพื่อแยกจำนวนเต็มได้
int foo = as< int >( jv[ " path.to.int " ] );
ที่นี่ "path.to.int"
คือเส้นทาง JSON ที่แสดงถึงการเจาะเข้าไปในคลาส JSON เช่น
{
"path" : {
"to" : {
"int" : 5
}
}
}
เราสามารถเลือกผ่านอาร์เรย์เช่นไวยากรณ์ในเส้นทาง JSON ได้เช่นกัน "path[5]"
จะเลือกองค์ประกอบที่ 5/สมาชิกของ "path"
หากคุณต้องการซีเรียลไลซ์เป็น JSON ไวยากรณ์เส้นทาง JSON ทำงานร่วมกับ from_json
, from_json_array
และ json_array_iterator
ด้วยเช่นกัน
to_json
std::string my_json_data = to_json( MyClass{} );
หรือทำให้อาร์เรย์ คอลเลกชัน ช่วง หรือมุมมองของสิ่งต่างๆ เป็นอนุกรม ต้องการเพียง std::begin(...)
และ std::end(...)
เท่านั้นจึงจะทำงานได้สำหรับประเภทนั้น สิ่งนี้ช่วยให้สามารถซีเรียลไลซ์ได้เมื่อประเภทนั้นไม่ใช่คอลเล็กชันที่สามารถสร้างได้
std::vector<MyClass> arry = ...;
std::string my_json_data = to_json_array( arry );
ข้อผิดพลาดในการแยกวิเคราะห์เริ่มต้นที่การขว้าง daw::json::json_exception
ซึ่งมีข้อมูลเกี่ยวกับสาเหตุและตำแหน่งของความล้มเหลว
หากปิดใช้งานข้อยกเว้น ไลบรารีจะเรียก std::terminate
เมื่อมีข้อผิดพลาดในการแยกวิเคราะห์ตามค่าเริ่มต้น
ในขณะที่การจัดการข้อผิดพลาดเริ่มต้นที่จะโยน daw::json::json_exception
กับข้อผิดพลาด หรือการเรียก std::terminate
หากข้อยกเว้นถูกปิดใช้งาน daw::json::daw_json_error_handler
หนึ่งสามารถเปลี่ยนพฤติกรรมนี้ได้โดยการตั้งค่าตัวชี้ฟังก์ชัน ข้อกำหนดเพียงอย่างเดียวคือฟังก์ชันจะไม่ส่งคืน ตัวอย่างที่ใช้สิ่งนี้อยู่ใน error_handling_bench_test.cpp
การตรวจสอบข้อผิดพลาดสามารถแก้ไขได้ตามแต่ละการวิเคราะห์ from_json
, from_json_array
, json_value
, json_array_iterator
และเหมือนกันทั้งหมดรองรับตัวเลือกการแยกวิเคราะห์ การโทรสามารถระบุ Parser Option ได้ ตัวเลือกที่มีอยู่ได้รับการบันทึกไว้ในรายการตำราอาหาร parser_policies
daw::json::json_exception
มีฟังก์ชันสมาชิก std::string_view reason( ) const
คล้ายกับ std::exception
's what( )
แต่ส่งคืน std::string
ที่มีบริบทมากกว่า what( )
ทำ หากคุณต้องการปิดการใช้งานข้อยกเว้นในสภาพแวดล้อมที่มี คุณสามารถกำหนด DAW_JSON_DONT_USE_EXCEPTIONS
เพื่อปิดการใช้งานข้อยกเว้นที่ส่งโดยไลบรารีหรือตั้งค่าตัวจัดการ ซึ่งไม่แนะนำอีกต่อไป เนื่องจากตัวจัดการสามารถตั้งค่าเป็นค่าเริ่มต้นอย่างใดอย่างหนึ่ง daw::json::default_error_handling_throwing
หรือ daw::json::default_error_handling_terminating
ซึ่งสามารถทำได้โดยการเขียนความเชี่ยวชาญพิเศษของ json_data_contract
ใน daw::json
เนมสเปซ ตัวอย่างเช่น:
# include < daw/json/daw_json_link.h >
# include < string >
# include < string_view >
# include < vector >
struct TestClass {
int i = 0 ;
double d = 0.0 ;
bool b = false ;
std::string s{};
std::vector< int > y{};
TestClass ( int Int, double Double, bool Bool, std::string S,
std::vector< int > Y)
: i(Int), d(Double), b(Bool), s(std::move( S ) ), y(std::move( Y )) {}
};
namespace daw ::json {
template <>
struct json_data_contract <TestClass> {
using type =
json_member_list<
json_number< " i " , int >,
json_number< " d " >,
json_bool< " b " >,
json_string< " s " >,
json_array< " y " , int >
>;
};
} // namespace daw::json
int main () {
std::string_view test_001_t_json_data = R"( {
"i":5,
"d":2.2e4,
"b":false,
"s":"hello world",
"y":[1,2,3,4]
} )" ;
std::string_view json_array_data = R"( [{
"i":5,
"d":2.2e4,
"b":false,
"s":"hello world",
"y":[1,2,3,4]
},{
"i":4,
"d":122e4,
"b":true,
"s":"goodbye world",
"y":[4,3,1,4]
}] )" ;
TestClass test_class = daw::json::from_json<TestClass>(test_001_t_json_data);
std::vector<TestClass> arry_of_test_class =
daw::json::from_json_array<TestClass>(test_001_t_json_data);
}
ดูในคอมไพเลอร์ Explorer
รองรับทั้งตัวสร้างแบบรวมและตัวสร้างผู้ใช้ คำอธิบายระบุค่าที่จำเป็นในการสร้างประเภทและคำสั่งซื้อของคุณ ลำดับที่ระบุคือลำดับที่พวกมันถูกวางลงในตัวสร้าง มีจุดปรับแต่งเพื่อให้มีวิธีสร้างประเภทของคุณด้วย ชั้นเรียนเช่น:
# include < daw/json/daw_json_link.h >
struct AggClass {
int a{};
double b{};
};
namespace daw ::json {
template <>
struct json_data_contract <AggClass> {
using type = json_member_list<
json_number< " a " , int >,
json_number< " b " >
>;
};
}
ใช้งานได้เช่นกัน เหมือนกัน แต่เป็น C++17
# include < daw/json/daw_json_link.h >
struct AggClass {
int a{};
double b{};
};
namespace daw ::json {
template <>
struct json_data_contract <AggClass> {
static inline constexpr char const a[] = " a " ;
static inline constexpr char const b[] = " b " ;
using type = json_member_list<
json_number<a, int >,
json_number<b>
>;
};
}
คำอธิบายคลาสเป็นแบบเรียกซ้ำกับสมาชิกย่อย การใช้ AggClass
ก่อนหน้านี้สามารถรวมไว้เป็นสมาชิกของคลาสอื่นได้
// See above for AggClass
struct MyClass {
AggClass other;
std::string_view some_name;
};
namespace daw ::json {
template <>
struct json_data_contract <MyClass> {
using type = json_member_list<
json_class< " other " , AggClass>,
json_string< " id " , std::string_view>
>;
};
}
ข้างต้นแมปคลาส MyClass
ที่มีคลาสอื่นที่อธิบาย AggClass นอกจากนี้ คุณจะเห็นว่าชื่อสมาชิกของคลาส C++ ไม่จำเป็นต้องตรงกับชื่อ JSON ที่แมป และสตริงนั้นสามารถใช้ std::string_view
เป็นประเภทผลลัพธ์ได้ นี่เป็นการปรับปรุงประสิทธิภาพที่สำคัญ หากคุณรับประกันได้ว่าบัฟเฟอร์ที่มีไฟล์ JSON จะคงอยู่ตราบเท่าที่คลาสนั้นยังคงอยู่
วนซ้ำอาร์เรย์ JSON ตัววนซ้ำอินพุต daw::json::json_array_iterator<JsonElement>
อนุญาตให้หนึ่งตัววนซ้ำผ่านอาร์เรย์ขององค์ประกอบ JSON ในทางเทคนิคแล้ว มันเป็นตัววนซ้ำอินพุต แต่สามารถจัดเก็บและนำมาใช้ซ้ำได้เหมือนกับตัววนซ้ำไปข้างหน้า มันไม่ได้ส่งคืนการอ้างอิงแต่เป็นค่า
# include < daw/json/daw_json_link.h >
# include < daw/json/daw_json_iterator.h >
# include < iostream >
struct AggClass {
int a{};
double b{};
};
namespace daw ::json {
template <>
struct json_data_contract <AggClass> {
using type = json_member_list<
json_number< " a " , int >,
json_number< " b " >
>;
};
} // namespace daw::json
int main () {
std::string json_array_data = R"( [
{"a":5,"b":2.2},
{"a":5,"b":3.14},
{"a":5,"b":0.122e44},
{"a":5334,"b":34342.2}
] )" ;
using iterator_t = daw::json::json_array_iterator<AggClass>;
auto pos =
std::find_if (
iterator_t (json_array_data),
iterator_t (),
[](AggClass const &element) {
return element. b > 1000.0 ;
}
);
if (pos == iterator_t ()) {
std::cout << " Not found n " ;
} else {
std::cout << " Found n " ;
}
}
การแยกวิเคราะห์สามารถเริ่มต้นที่สมาชิกหรือองค์ประกอบเฉพาะ สามารถระบุพาธสมาชิกทางเลือกไปยัง from_json
, from_json_array
, json_value
, json_array_iterator
และเหมือนกันได้ รูปแบบนี้เป็นรายการชื่อสมาชิกที่คั่นด้วยจุด และดัชนีอาร์เรย์ (เป็นทางเลือก) เช่น member0.member1
ซึ่งเหมือนกับการแยกวิเคราะห์จาก:
{
"member0" : {
"member1" : {}
}
}
หรือ member0[5].member1
ซึ่งจะเริ่มแยกวิเคราะห์ที่ "member1" ในเอกสารเช่น:
{
"member0" : [
" a " ,
" b " ,
" c " ,
" d " ,
" e " ,
{
"member1" : " "
}
]
}
หรือ
{
"member0" : {
"a" : " " ,
"b" : " " ,
"c" : " " ,
"d" : " " ,
"e" : " " ,
"f" : {
"member1" : " "
}
}
}
ความคิดเห็นได้รับการสนับสนุนเมื่อมีการใช้นโยบาย parser ในปัจจุบัน นโยบายความคิดเห็นมีสองรูปแบบ
//
ความคิดเห็นบรรทัด และสไตล์ C /* */
ความคิดเห็น { // This is a comment
"a" /*this is also a comment*/: "a's value"
}
#
ไลน์คอมเม้น { # This is a comment
"a" #this is also a comment
: "a's value"
}
นโยบายความคิดเห็นสามารถตั้งค่าได้ผ่าน PolicyCommentTypes
ดู parser_policies สำหรับข้อมูลเพิ่มเติม
หากต้องการเปิดใช้งานการทำให้เป็นอนุกรมเราต้องสร้างฟังก์ชันคงที่เพิ่มเติมในความเชี่ยวชาญของคุณของ json_data_contract
ที่เรียกว่า to_json_data( Thing const & );
ที่ส่งคืนสมาชิกจำนวนหนึ่ง มันจะจัดให้มีการแมปจากประเภทของคุณกับอาร์กิวเมนต์ที่ให้ไว้ในคำอธิบายชั้นเรียน หากต้องการซีเรียลไลซ์เป็นสตริง JSON จะมีการเรียก to_json( my_thing );
โดยที่ my_thing
เป็นประเภทที่ลงทะเบียนไว้หรือประเภทพื้นฐานประเภทใดประเภทหนึ่ง เช่น คอนเทนเนอร์ แผนที่ สตริง บูล และตัวเลข ผลลัพธ์ของ to_json_data( Thing const & )
วิธีการคงที่คือ tuple
ที่องค์ประกอบตรงกับลำดับใน json_data_contract
type alias type
ที่มาคู่กัน เนื่องจากวิธีการใช้ tuple's ที่มีองค์ประกอบ rvalue จะส่งผลให้เกิดข้อผิดพลาดในการใช้งานหลังการทำลาย คอมไพเลอร์จะเกิดข้อผิดพลาดหากสิ่งนี้เกิดขึ้น การรวม <daw/daw_tuple_forward.h>
และวิธีการ daw::forward_nonrvalue_as_tuple
แทนจะจัดเก็บค่า rvalues แทนที่จะส่งต่อโดยการอ้างอิง บ่อยครั้งเป็นผลจากการคำนวณองค์ประกอบทูเพิล ใช้ตัวอย่างข้างต้นให้เพิ่มวิธีการ to_json_data
# include < daw/json/daw_json_link.h >
# include < tuple >
struct AggClass {
int a;
double b;
};
namespace daw ::json {
template <>
struct json_data_contract <AggClass> {
using type = json_member_list<
json_number< " a " , int >,
json_number< " b " >
>;
static constexpr auto to_json_data ( AggClass const & value ) {
return std::forward_as_tuple ( value. a , value. b );
}
};
}
// ...
AggData value = // ...;
std::string test_001_t_json_data = to_json( value );
// or
std::vector<AggData> values = // ...;
std::string json_array_data = to_json_array( values );
อีกทางหนึ่งสามารถส่งออกไปยังประเภท WritableOutput ใดก็ได้ โดยค่าเริ่มต้นจะรวมถึง FILE*, iostreams, คอนเทนเนอร์ของอักขระ และตัวชี้อักขระ ใน json_data_constract
ของประเภทของคุณ หรือหากเลือกใช้ เราสามารถรับตัวดำเนินการ ostream<< สำหรับประเภทที่แทรก json ลงในสตรีมเอาต์พุตโดยการเพิ่มนามแฝงประเภทชื่อ opt_into_iostreams
ซึ่งเป็นประเภทนามแฝงที่ไม่สำคัญ และรวม daw/json/daw_json_iostream.h
. ตัวอย่างเช่น
# include < daw/json/daw_json_link.h >
# include < daw/json/daw_json_iostream.h >
# include < tuple >
struct AggClass {
int a{};
double b{};
};
namespace daw ::json {
template <>
struct json_data_contract <AggClass> {
using opt_into_iostreams = void ;
using type = json_member_list<
json_number< " a " , int >,
json_number< " b " >
>;
static inline auto to_json_data ( AggClass const & value ) {
return std::forward_as_tuple ( value. a , value. b );
}
};
}
// ...
AggData value = // ...;
std::cout << value << ' n ' ;
// or
std::vector<AggData> values = // ...;
std::cout << values << ' n ' ;
ตัวอย่างการทำงานสามารถพบได้ที่ daw_json_iostream_test.cpp หรือบนคอมไพเลอร์ explorer
error: pointer to subobject of string literal is not allowed in a template argument
constexpr char const member_name[] = " member_name " ;
// ...
json_link<member_name, Type>
มีคำจำกัดความบางประการที่ส่งผลต่อวิธีการทำงานของ JSON Link
DAW_JSON_DONT_USE_EXCEPTIONS
- ควบคุมว่าจะอนุญาตให้มีข้อยกเว้นหรือไม่ หากไม่เป็นเช่นนั้น std::terminate()
กับข้อผิดพลาดจะเกิดขึ้น สิ่งนี้จะเกิดขึ้นโดยอัตโนมัติหากปิดการใช้งานข้อยกเว้น (เช่น -fno-exceptions
)DAW_ALLOW_SSE42
- อนุญาตโหมดทดลอง SSE42 โดยทั่วไปโหมด constexpr จะเร็วกว่าDAW_JSON_NO_CONST_EXPR
- สามารถใช้เพื่ออนุญาตให้สร้างคลาสโดยไม่ต้องย้าย/คัดลอกสมาชิกพิเศษจากข้อมูล JSON ก่อน C++ 20 โหมดนี้จะไม่ทำงานในนิพจน์คงที่ก่อน C++20 เมื่อไม่จำเป็นต้องใช้แฟล็กนี้อีกต่อไป คอมไพเลอร์รุ่นเก่าอาจยังใช้งานได้ แต่ในการทดสอบบางอย่างทำให้เกิดข้อผิดพลาดของ ICE หรือคอมไพล์เนื่องจากการรองรับ buggy C++17 บ่อยครั้งการไม่ใช้ constexpr ก็ช่วยได้เช่นกัน
json_key_value
std::multimap<std::string, T>
หรือ std::vector<std::pair<std::string, T>>
สมาชิกทั้งหมดจะถูกรักษาไว้โดยลำดับแรก อีกทางหนึ่ง ประเภท json_value
จะอนุญาตให้วนซ้ำสมาชิกคลาสและแยกวิเคราะห์ข้อมูลที่ถูกต้องแบบขี้เกียจ ดูค่าคีย์ตำราอาหารซึ่งสาธิตวิธีการเหล่านี้