123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220 |
- // __ _____ _____ _____
- // __| | __| | | | JSON for Modern C++
- // | | |__ | | | | | | version 3.11.2
- // |_____|_____|_____|_|___| https://github.com/nlohmann/json
- //
- // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
- // SPDX-License-Identifier: MIT
- /****************************************************************************\
- * Note on documentation: The source files contain links to the online *
- * documentation of the public API at https://json.nlohmann.me. This URL *
- * contains the most recent documentation and should also be applicable to *
- * previous versions; documentation for deprecated functions is not *
- * removed, but marked deprecated. See "Generate documentation" section in *
- * file docs/README.md. *
- \****************************************************************************/
- #ifndef INCLUDE_NLOHMANN_JSON_HPP_
- #define INCLUDE_NLOHMANN_JSON_HPP_
- #include <algorithm> // all_of, find, for_each
- #include <cstddef> // nullptr_t, ptrdiff_t, size_t
- #include <functional> // hash, less
- #include <initializer_list> // initializer_list
- #ifndef JSON_NO_IO
- #include <iosfwd> // istream, ostream
- #endif // JSON_NO_IO
- #include <iterator> // random_access_iterator_tag
- #include <memory> // unique_ptr
- #include <string> // string, stoi, to_string
- #include <utility> // declval, forward, move, pair, swap
- #include <vector> // vector
- #include <nlohmann/adl_serializer.hpp>
- #include <nlohmann/byte_container_with_subtype.hpp>
- #include <nlohmann/detail/conversions/from_json.hpp>
- #include <nlohmann/detail/conversions/to_json.hpp>
- #include <nlohmann/detail/exceptions.hpp>
- #include <nlohmann/detail/hash.hpp>
- #include <nlohmann/detail/input/binary_reader.hpp>
- #include <nlohmann/detail/input/input_adapters.hpp>
- #include <nlohmann/detail/input/lexer.hpp>
- #include <nlohmann/detail/input/parser.hpp>
- #include <nlohmann/detail/iterators/internal_iterator.hpp>
- #include <nlohmann/detail/iterators/iter_impl.hpp>
- #include <nlohmann/detail/iterators/iteration_proxy.hpp>
- #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
- #include <nlohmann/detail/iterators/primitive_iterator.hpp>
- #include <nlohmann/detail/json_custom_base_class.hpp>
- #include <nlohmann/detail/json_pointer.hpp>
- #include <nlohmann/detail/json_ref.hpp>
- #include <nlohmann/detail/macro_scope.hpp>
- #include <nlohmann/detail/string_concat.hpp>
- #include <nlohmann/detail/string_escape.hpp>
- #include <nlohmann/detail/meta/cpp_future.hpp>
- #include <nlohmann/detail/meta/type_traits.hpp>
- #include <nlohmann/detail/output/binary_writer.hpp>
- #include <nlohmann/detail/output/output_adapters.hpp>
- #include <nlohmann/detail/output/serializer.hpp>
- #include <nlohmann/detail/value_t.hpp>
- #include <nlohmann/json_fwd.hpp>
- #include <nlohmann/ordered_map.hpp>
- #if defined(JSON_HAS_CPP_17)
- #include <any>
- #include <string_view>
- #endif
- /*!
- @brief namespace for Niels Lohmann
- @see https://github.com/nlohmann
- @since version 1.0.0
- */
- NLOHMANN_JSON_NAMESPACE_BEGIN
- /*!
- @brief a class to store JSON values
- @internal
- @invariant The member variables @a m_value and @a m_type have the following
- relationship:
- - If `m_type == value_t::object`, then `m_value.object != nullptr`.
- - If `m_type == value_t::array`, then `m_value.array != nullptr`.
- - If `m_type == value_t::string`, then `m_value.string != nullptr`.
- The invariants are checked by member function assert_invariant().
- @note ObjectType trick from https://stackoverflow.com/a/9860911
- @endinternal
- @since version 1.0.0
- @nosubgrouping
- */
- NLOHMANN_BASIC_JSON_TPL_DECLARATION
- class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
- : public ::nlohmann::detail::json_base_class<CustomBaseClass>
- {
- private:
- template<detail::value_t> friend struct detail::external_constructor;
- template<typename>
- friend class ::nlohmann::json_pointer;
- // can be restored when json_pointer backwards compatibility is removed
- // friend ::nlohmann::json_pointer<StringType>;
- template<typename BasicJsonType, typename InputType>
- friend class ::nlohmann::detail::parser;
- friend ::nlohmann::detail::serializer<basic_json>;
- template<typename BasicJsonType>
- friend class ::nlohmann::detail::iter_impl;
- template<typename BasicJsonType, typename CharType>
- friend class ::nlohmann::detail::binary_writer;
- template<typename BasicJsonType, typename InputType, typename SAX>
- friend class ::nlohmann::detail::binary_reader;
- template<typename BasicJsonType>
- friend class ::nlohmann::detail::json_sax_dom_parser;
- template<typename BasicJsonType>
- friend class ::nlohmann::detail::json_sax_dom_callback_parser;
- friend class ::nlohmann::detail::exception;
- /// workaround type for MSVC
- using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
- using json_base_class_t = ::nlohmann::detail::json_base_class<CustomBaseClass>;
- JSON_PRIVATE_UNLESS_TESTED:
- // convenience aliases for types residing in namespace detail;
- using lexer = ::nlohmann::detail::lexer_base<basic_json>;
- template<typename InputAdapterType>
- static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser(
- InputAdapterType adapter,
- detail::parser_callback_t<basic_json>cb = nullptr,
- const bool allow_exceptions = true,
- const bool ignore_comments = false
- )
- {
- return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
- std::move(cb), allow_exceptions, ignore_comments);
- }
- private:
- using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
- template<typename BasicJsonType>
- using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
- template<typename BasicJsonType>
- using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
- template<typename Iterator>
- using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
- template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
- template<typename CharType>
- using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
- template<typename InputType>
- using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>;
- template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
- JSON_PRIVATE_UNLESS_TESTED:
- using serializer = ::nlohmann::detail::serializer<basic_json>;
- public:
- using value_t = detail::value_t;
- /// JSON Pointer, see @ref nlohmann::json_pointer
- using json_pointer = ::nlohmann::json_pointer<StringType>;
- template<typename T, typename SFINAE>
- using json_serializer = JSONSerializer<T, SFINAE>;
- /// how to treat decoding errors
- using error_handler_t = detail::error_handler_t;
- /// how to treat CBOR tags
- using cbor_tag_handler_t = detail::cbor_tag_handler_t;
- /// helper type for initializer lists of basic_json values
- using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
- using input_format_t = detail::input_format_t;
- /// SAX interface type, see @ref nlohmann::json_sax
- using json_sax_t = json_sax<basic_json>;
- ////////////////
- // exceptions //
- ////////////////
- /// @name exceptions
- /// Classes to implement user-defined exceptions.
- /// @{
- using exception = detail::exception;
- using parse_error = detail::parse_error;
- using invalid_iterator = detail::invalid_iterator;
- using type_error = detail::type_error;
- using out_of_range = detail::out_of_range;
- using other_error = detail::other_error;
- /// @}
- /////////////////////
- // container types //
- /////////////////////
- /// @name container types
- /// The canonic container types to use @ref basic_json like any other STL
- /// container.
- /// @{
- /// the type of elements in a basic_json container
- using value_type = basic_json;
- /// the type of an element reference
- using reference = value_type&;
- /// the type of an element const reference
- using const_reference = const value_type&;
- /// a type to represent differences between iterators
- using difference_type = std::ptrdiff_t;
- /// a type to represent container sizes
- using size_type = std::size_t;
- /// the allocator type
- using allocator_type = AllocatorType<basic_json>;
- /// the type of an element pointer
- using pointer = typename std::allocator_traits<allocator_type>::pointer;
- /// the type of an element const pointer
- using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
- /// an iterator for a basic_json container
- using iterator = iter_impl<basic_json>;
- /// a const iterator for a basic_json container
- using const_iterator = iter_impl<const basic_json>;
- /// a reverse iterator for a basic_json container
- using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
- /// a const reverse iterator for a basic_json container
- using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
- /// @}
- /// @brief returns the allocator associated with the container
- /// @sa https://json.nlohmann.me/api/basic_json/get_allocator/
- static allocator_type get_allocator()
- {
- return allocator_type();
- }
- /// @brief returns version information on the library
- /// @sa https://json.nlohmann.me/api/basic_json/meta/
- JSON_HEDLEY_WARN_UNUSED_RESULT
- static basic_json meta()
- {
- basic_json result;
- result["copyright"] = "(C) 2013-2022 Niels Lohmann";
- result["name"] = "JSON for Modern C++";
- result["url"] = "https://github.com/nlohmann/json";
- result["version"]["string"] =
- detail::concat(std::to_string(NLOHMANN_JSON_VERSION_MAJOR), '.',
- std::to_string(NLOHMANN_JSON_VERSION_MINOR), '.',
- std::to_string(NLOHMANN_JSON_VERSION_PATCH));
- result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
- result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
- result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
- #ifdef _WIN32
- result["platform"] = "win32";
- #elif defined __linux__
- result["platform"] = "linux";
- #elif defined __APPLE__
- result["platform"] = "apple";
- #elif defined __unix__
- result["platform"] = "unix";
- #else
- result["platform"] = "unknown";
- #endif
- #if defined(__ICC) || defined(__INTEL_COMPILER)
- result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
- #elif defined(__clang__)
- result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
- #elif defined(__GNUC__) || defined(__GNUG__)
- result["compiler"] = {{"family", "gcc"}, {"version", detail::concat(
- std::to_string(__GNUC__), '.',
- std::to_string(__GNUC_MINOR__), '.',
- std::to_string(__GNUC_PATCHLEVEL__))
- }
- };
- #elif defined(__HP_cc) || defined(__HP_aCC)
- result["compiler"] = "hp"
- #elif defined(__IBMCPP__)
- result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
- #elif defined(_MSC_VER)
- result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
- #elif defined(__PGI)
- result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
- #elif defined(__SUNPRO_CC)
- result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
- #else
- result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
- #endif
- #if defined(_MSVC_LANG)
- result["compiler"]["c++"] = std::to_string(_MSVC_LANG);
- #elif defined(__cplusplus)
- result["compiler"]["c++"] = std::to_string(__cplusplus);
- #else
- result["compiler"]["c++"] = "unknown";
- #endif
- return result;
- }
- ///////////////////////////
- // JSON value data types //
- ///////////////////////////
- /// @name JSON value data types
- /// The data types to store a JSON value. These types are derived from
- /// the template arguments passed to class @ref basic_json.
- /// @{
- /// @brief default object key comparator type
- /// The actual object key comparator type (@ref object_comparator_t) may be
- /// different.
- /// @sa https://json.nlohmann.me/api/basic_json/default_object_comparator_t/
- #if defined(JSON_HAS_CPP_14)
- // use of transparent comparator avoids unnecessary repeated construction of temporaries
- // in functions involving lookup by key with types other than object_t::key_type (aka. StringType)
- using default_object_comparator_t = std::less<>;
- #else
- using default_object_comparator_t = std::less<StringType>;
- #endif
- /// @brief a type for an object
- /// @sa https://json.nlohmann.me/api/basic_json/object_t/
- using object_t = ObjectType<StringType,
- basic_json,
- default_object_comparator_t,
- AllocatorType<std::pair<const StringType,
- basic_json>>>;
- /// @brief a type for an array
- /// @sa https://json.nlohmann.me/api/basic_json/array_t/
- using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
- /// @brief a type for a string
- /// @sa https://json.nlohmann.me/api/basic_json/string_t/
- using string_t = StringType;
- /// @brief a type for a boolean
- /// @sa https://json.nlohmann.me/api/basic_json/boolean_t/
- using boolean_t = BooleanType;
- /// @brief a type for a number (integer)
- /// @sa https://json.nlohmann.me/api/basic_json/number_integer_t/
- using number_integer_t = NumberIntegerType;
- /// @brief a type for a number (unsigned)
- /// @sa https://json.nlohmann.me/api/basic_json/number_unsigned_t/
- using number_unsigned_t = NumberUnsignedType;
- /// @brief a type for a number (floating-point)
- /// @sa https://json.nlohmann.me/api/basic_json/number_float_t/
- using number_float_t = NumberFloatType;
- /// @brief a type for a packed binary type
- /// @sa https://json.nlohmann.me/api/basic_json/binary_t/
- using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
- /// @brief object key comparator type
- /// @sa https://json.nlohmann.me/api/basic_json/object_comparator_t/
- using object_comparator_t = detail::actual_object_comparator_t<basic_json>;
- /// @}
- private:
- /// helper for exception-safe object creation
- template<typename T, typename... Args>
- JSON_HEDLEY_RETURNS_NON_NULL
- static T* create(Args&& ... args)
- {
- AllocatorType<T> alloc;
- using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
- auto deleter = [&](T * obj)
- {
- AllocatorTraits::deallocate(alloc, obj, 1);
- };
- std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter);
- AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...);
- JSON_ASSERT(obj != nullptr);
- return obj.release();
- }
- ////////////////////////
- // JSON value storage //
- ////////////////////////
- JSON_PRIVATE_UNLESS_TESTED:
- /*!
- @brief a JSON value
- The actual storage for a JSON value of the @ref basic_json class. This
- union combines the different storage types for the JSON value types
- defined in @ref value_t.
- JSON type | value_t type | used type
- --------- | --------------- | ------------------------
- object | object | pointer to @ref object_t
- array | array | pointer to @ref array_t
- string | string | pointer to @ref string_t
- boolean | boolean | @ref boolean_t
- number | number_integer | @ref number_integer_t
- number | number_unsigned | @ref number_unsigned_t
- number | number_float | @ref number_float_t
- binary | binary | pointer to @ref binary_t
- null | null | *no value is stored*
- @note Variable-length types (objects, arrays, and strings) are stored as
- pointers. The size of the union should not exceed 64 bits if the default
- value types are used.
- @since version 1.0.0
- */
- union json_value
- {
- /// object (stored with pointer to save storage)
- object_t* object;
- /// array (stored with pointer to save storage)
- array_t* array;
- /// string (stored with pointer to save storage)
- string_t* string;
- /// binary (stored with pointer to save storage)
- binary_t* binary;
- /// boolean
- boolean_t boolean;
- /// number (integer)
- number_integer_t number_integer;
- /// number (unsigned integer)
- number_unsigned_t number_unsigned;
- /// number (floating-point)
- number_float_t number_float;
- /// default constructor (for null values)
- json_value() = default;
- /// constructor for booleans
- json_value(boolean_t v) noexcept : boolean(v) {}
- /// constructor for numbers (integer)
- json_value(number_integer_t v) noexcept : number_integer(v) {}
- /// constructor for numbers (unsigned)
- json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
- /// constructor for numbers (floating-point)
- json_value(number_float_t v) noexcept : number_float(v) {}
- /// constructor for empty values of a given type
- json_value(value_t t)
- {
- switch (t)
- {
- case value_t::object:
- {
- object = create<object_t>();
- break;
- }
- case value_t::array:
- {
- array = create<array_t>();
- break;
- }
- case value_t::string:
- {
- string = create<string_t>("");
- break;
- }
- case value_t::binary:
- {
- binary = create<binary_t>();
- break;
- }
- case value_t::boolean:
- {
- boolean = static_cast<boolean_t>(false);
- break;
- }
- case value_t::number_integer:
- {
- number_integer = static_cast<number_integer_t>(0);
- break;
- }
- case value_t::number_unsigned:
- {
- number_unsigned = static_cast<number_unsigned_t>(0);
- break;
- }
- case value_t::number_float:
- {
- number_float = static_cast<number_float_t>(0.0);
- break;
- }
- case value_t::null:
- {
- object = nullptr; // silence warning, see #821
- break;
- }
- case value_t::discarded:
- default:
- {
- object = nullptr; // silence warning, see #821
- if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
- {
- JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.11.2", nullptr)); // LCOV_EXCL_LINE
- }
- break;
- }
- }
- }
- /// constructor for strings
- json_value(const string_t& value) : string(create<string_t>(value)) {}
- /// constructor for rvalue strings
- json_value(string_t&& value) : string(create<string_t>(std::move(value))) {}
- /// constructor for objects
- json_value(const object_t& value) : object(create<object_t>(value)) {}
- /// constructor for rvalue objects
- json_value(object_t&& value) : object(create<object_t>(std::move(value))) {}
- /// constructor for arrays
- json_value(const array_t& value) : array(create<array_t>(value)) {}
- /// constructor for rvalue arrays
- json_value(array_t&& value) : array(create<array_t>(std::move(value))) {}
- /// constructor for binary arrays
- json_value(const typename binary_t::container_type& value) : binary(create<binary_t>(value)) {}
- /// constructor for rvalue binary arrays
- json_value(typename binary_t::container_type&& value) : binary(create<binary_t>(std::move(value))) {}
- /// constructor for binary arrays (internal type)
- json_value(const binary_t& value) : binary(create<binary_t>(value)) {}
- /// constructor for rvalue binary arrays (internal type)
- json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {}
- void destroy(value_t t)
- {
- if (t == value_t::array || t == value_t::object)
- {
- // flatten the current json_value to a heap-allocated stack
- std::vector<basic_json> stack;
- // move the top-level items to stack
- if (t == value_t::array)
- {
- stack.reserve(array->size());
- std::move(array->begin(), array->end(), std::back_inserter(stack));
- }
- else
- {
- stack.reserve(object->size());
- for (auto&& it : *object)
- {
- stack.push_back(std::move(it.second));
- }
- }
- while (!stack.empty())
- {
- // move the last item to local variable to be processed
- basic_json current_item(std::move(stack.back()));
- stack.pop_back();
- // if current_item is array/object, move
- // its children to the stack to be processed later
- if (current_item.is_array())
- {
- std::move(current_item.m_value.array->begin(), current_item.m_value.array->end(), std::back_inserter(stack));
- current_item.m_value.array->clear();
- }
- else if (current_item.is_object())
- {
- for (auto&& it : *current_item.m_value.object)
- {
- stack.push_back(std::move(it.second));
- }
- current_item.m_value.object->clear();
- }
- // it's now safe that current_item get destructed
- // since it doesn't have any children
- }
- }
- switch (t)
- {
- case value_t::object:
- {
- AllocatorType<object_t> alloc;
- std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
- std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
- break;
- }
- case value_t::array:
- {
- AllocatorType<array_t> alloc;
- std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
- std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
- break;
- }
- case value_t::string:
- {
- AllocatorType<string_t> alloc;
- std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
- std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
- break;
- }
- case value_t::binary:
- {
- AllocatorType<binary_t> alloc;
- std::allocator_traits<decltype(alloc)>::destroy(alloc, binary);
- std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1);
- break;
- }
- case value_t::null:
- case value_t::boolean:
- case value_t::number_integer:
- case value_t::number_unsigned:
- case value_t::number_float:
- case value_t::discarded:
- default:
- {
- break;
- }
- }
- }
- };
- private:
- /*!
- @brief checks the class invariants
- This function asserts the class invariants. It needs to be called at the
- end of every constructor to make sure that created objects respect the
- invariant. Furthermore, it has to be called each time the type of a JSON
- value is changed, because the invariant expresses a relationship between
- @a m_type and @a m_value.
- Furthermore, the parent relation is checked for arrays and objects: If
- @a check_parents true and the value is an array or object, then the
- container's elements must have the current value as parent.
- @param[in] check_parents whether the parent relation should be checked.
- The value is true by default and should only be set to false
- during destruction of objects when the invariant does not
- need to hold.
- */
- void assert_invariant(bool check_parents = true) const noexcept
- {
- JSON_ASSERT(m_type != value_t::object || m_value.object != nullptr);
- JSON_ASSERT(m_type != value_t::array || m_value.array != nullptr);
- JSON_ASSERT(m_type != value_t::string || m_value.string != nullptr);
- JSON_ASSERT(m_type != value_t::binary || m_value.binary != nullptr);
- #if JSON_DIAGNOSTICS
- JSON_TRY
- {
- // cppcheck-suppress assertWithSideEffect
- JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j)
- {
- return j.m_parent == this;
- }));
- }
- JSON_CATCH(...) {} // LCOV_EXCL_LINE
- #endif
- static_cast<void>(check_parents);
- }
- void set_parents()
- {
- #if JSON_DIAGNOSTICS
- switch (m_type)
- {
- case value_t::array:
- {
- for (auto& element : *m_value.array)
- {
- element.m_parent = this;
- }
- break;
- }
- case value_t::object:
- {
- for (auto& element : *m_value.object)
- {
- element.second.m_parent = this;
- }
- break;
- }
- case value_t::null:
- case value_t::string:
- case value_t::boolean:
- case value_t::number_integer:
- case value_t::number_unsigned:
- case value_t::number_float:
- case value_t::binary:
- case value_t::discarded:
- default:
- break;
- }
- #endif
- }
- iterator set_parents(iterator it, typename iterator::difference_type count_set_parents)
- {
- #if JSON_DIAGNOSTICS
- for (typename iterator::difference_type i = 0; i < count_set_parents; ++i)
- {
- (it + i)->m_parent = this;
- }
- #else
- static_cast<void>(count_set_parents);
- #endif
- return it;
- }
- reference set_parent(reference j, std::size_t old_capacity = static_cast<std::size_t>(-1))
- {
- #if JSON_DIAGNOSTICS
- if (old_capacity != static_cast<std::size_t>(-1))
- {
- // see https://github.com/nlohmann/json/issues/2838
- JSON_ASSERT(type() == value_t::array);
- if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity))
- {
- // capacity has changed: update all parents
- set_parents();
- return j;
- }
- }
- // ordered_json uses a vector internally, so pointers could have
- // been invalidated; see https://github.com/nlohmann/json/issues/2962
- #ifdef JSON_HEDLEY_MSVC_VERSION
- #pragma warning(push )
- #pragma warning(disable : 4127) // ignore warning to replace if with if constexpr
- #endif
- if (detail::is_ordered_map<object_t>::value)
- {
- set_parents();
- return j;
- }
- #ifdef JSON_HEDLEY_MSVC_VERSION
- #pragma warning( pop )
- #endif
- j.m_parent = this;
- #else
- static_cast<void>(j);
- static_cast<void>(old_capacity);
- #endif
- return j;
- }
- public:
- //////////////////////////
- // JSON parser callback //
- //////////////////////////
- /// @brief parser event types
- /// @sa https://json.nlohmann.me/api/basic_json/parse_event_t/
- using parse_event_t = detail::parse_event_t;
- /// @brief per-element parser callback type
- /// @sa https://json.nlohmann.me/api/basic_json/parser_callback_t/
- using parser_callback_t = detail::parser_callback_t<basic_json>;
- //////////////////
- // constructors //
- //////////////////
- /// @name constructors and destructors
- /// Constructors of class @ref basic_json, copy/move constructor, copy
- /// assignment, static functions creating objects, and the destructor.
- /// @{
- /// @brief create an empty value with a given type
- /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
- basic_json(const value_t v)
- : m_type(v), m_value(v)
- {
- assert_invariant();
- }
- /// @brief create a null object
- /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
- basic_json(std::nullptr_t = nullptr) noexcept // NOLINT(bugprone-exception-escape)
- : basic_json(value_t::null)
- {
- assert_invariant();
- }
- /// @brief create a JSON value from compatible types
- /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
- template < typename CompatibleType,
- typename U = detail::uncvref_t<CompatibleType>,
- detail::enable_if_t <
- !detail::is_basic_json<U>::value && detail::is_compatible_type<basic_json_t, U>::value, int > = 0 >
- basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape)
- JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
- std::forward<CompatibleType>(val))))
- {
- JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
- set_parents();
- assert_invariant();
- }
- /// @brief create a JSON value from an existing one
- /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
- template < typename BasicJsonType,
- detail::enable_if_t <
- detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 >
- basic_json(const BasicJsonType& val)
- {
- using other_boolean_t = typename BasicJsonType::boolean_t;
- using other_number_float_t = typename BasicJsonType::number_float_t;
- using other_number_integer_t = typename BasicJsonType::number_integer_t;
- using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
- using other_string_t = typename BasicJsonType::string_t;
- using other_object_t = typename BasicJsonType::object_t;
- using other_array_t = typename BasicJsonType::array_t;
- using other_binary_t = typename BasicJsonType::binary_t;
- switch (val.type())
- {
- case value_t::boolean:
- JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
- break;
- case value_t::number_float:
- JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
- break;
- case value_t::number_integer:
- JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
- break;
- case value_t::number_unsigned:
- JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
- break;
- case value_t::string:
- JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
- break;
- case value_t::object:
- JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
- break;
- case value_t::array:
- JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
- break;
- case value_t::binary:
- JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>());
- break;
- case value_t::null:
- *this = nullptr;
- break;
- case value_t::discarded:
- m_type = value_t::discarded;
- break;
- default: // LCOV_EXCL_LINE
- JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
- }
- JSON_ASSERT(m_type == val.type());
- set_parents();
- assert_invariant();
- }
- /// @brief create a container (array or object) from an initializer list
- /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
- basic_json(initializer_list_t init,
- bool type_deduction = true,
- value_t manual_type = value_t::array)
- {
- // check if each element is an array with two elements whose first
- // element is a string
- bool is_an_object = std::all_of(init.begin(), init.end(),
- [](const detail::json_ref<basic_json>& element_ref)
- {
- return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[0].is_string();
- });
- // adjust type if type deduction is not wanted
- if (!type_deduction)
- {
- // if array is wanted, do not create an object though possible
- if (manual_type == value_t::array)
- {
- is_an_object = false;
- }
- // if object is wanted but impossible, throw an exception
- if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object))
- {
- JSON_THROW(type_error::create(301, "cannot create object from initializer list", nullptr));
- }
- }
- if (is_an_object)
- {
- // the initializer list is a list of pairs -> create object
- m_type = value_t::object;
- m_value = value_t::object;
- for (auto& element_ref : init)
- {
- auto element = element_ref.moved_or_copied();
- m_value.object->emplace(
- std::move(*((*element.m_value.array)[0].m_value.string)),
- std::move((*element.m_value.array)[1]));
- }
- }
- else
- {
- // the initializer list describes an array -> create array
- m_type = value_t::array;
- m_value.array = create<array_t>(init.begin(), init.end());
- }
- set_parents();
- assert_invariant();
- }
- /// @brief explicitly create a binary array (without subtype)
- /// @sa https://json.nlohmann.me/api/basic_json/binary/
- JSON_HEDLEY_WARN_UNUSED_RESULT
- static basic_json binary(const typename binary_t::container_type& init)
- {
- auto res = basic_json();
- res.m_type = value_t::binary;
- res.m_value = init;
- return res;
- }
- /// @brief explicitly create a binary array (with subtype)
- /// @sa https://json.nlohmann.me/api/basic_json/binary/
- JSON_HEDLEY_WARN_UNUSED_RESULT
- static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype)
- {
- auto res = basic_json();
- res.m_type = value_t::binary;
- res.m_value = binary_t(init, subtype);
- return res;
- }
- /// @brief explicitly create a binary array
- /// @sa https://json.nlohmann.me/api/basic_json/binary/
- JSON_HEDLEY_WARN_UNUSED_RESULT
- static basic_json binary(typename binary_t::container_type&& init)
- {
- auto res = basic_json();
- res.m_type = value_t::binary;
- res.m_value = std::move(init);
- return res;
- }
- /// @brief explicitly create a binary array (with subtype)
- /// @sa https://json.nlohmann.me/api/basic_json/binary/
- JSON_HEDLEY_WARN_UNUSED_RESULT
- static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype)
- {
- auto res = basic_json();
- res.m_type = value_t::binary;
- res.m_value = binary_t(std::move(init), subtype);
- return res;
- }
- /// @brief explicitly create an array from an initializer list
- /// @sa https://json.nlohmann.me/api/basic_json/array/
- JSON_HEDLEY_WARN_UNUSED_RESULT
- static basic_json array(initializer_list_t init = {})
- {
- return basic_json(init, false, value_t::array);
- }
- /// @brief explicitly create an object from an initializer list
- /// @sa https://json.nlohmann.me/api/basic_json/object/
- JSON_HEDLEY_WARN_UNUSED_RESULT
- static basic_json object(initializer_list_t init = {})
- {
- return basic_json(init, false, value_t::object);
- }
- /// @brief construct an array with count copies of given value
- /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
- basic_json(size_type cnt, const basic_json& val)
- : m_type(value_t::array)
- {
- m_value.array = create<array_t>(cnt, val);
- set_parents();
- assert_invariant();
- }
- /// @brief construct a JSON container given an iterator range
- /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
- template < class InputIT, typename std::enable_if <
- std::is_same<InputIT, typename basic_json_t::iterator>::value ||
- std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 >
- basic_json(InputIT first, InputIT last)
- {
- JSON_ASSERT(first.m_object != nullptr);
- JSON_ASSERT(last.m_object != nullptr);
- // make sure iterator fits the current value
- if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
- {
- JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", nullptr));
- }
- // copy type from first iterator
- m_type = first.m_object->m_type;
- // check if iterator range is complete for primitive values
- switch (m_type)
- {
- case value_t::boolean:
- case value_t::number_float:
- case value_t::number_integer:
- case value_t::number_unsigned:
- case value_t::string:
- {
- if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
- || !last.m_it.primitive_iterator.is_end()))
- {
- JSON_THROW(invalid_iterator::create(204, "iterators out of range", first.m_object));
- }
- break;
- }
- case value_t::null:
- case value_t::object:
- case value_t::array:
- case value_t::binary:
- case value_t::discarded:
- default:
- break;
- }
- switch (m_type)
- {
- case value_t::number_integer:
- {
- m_value.number_integer = first.m_object->m_value.number_integer;
- break;
- }
- case value_t::number_unsigned:
- {
- m_value.number_unsigned = first.m_object->m_value.number_unsigned;
- break;
- }
- case value_t::number_float:
- {
- m_value.number_float = first.m_object->m_value.number_float;
- break;
- }
- case value_t::boolean:
- {
- m_value.boolean = first.m_object->m_value.boolean;
- break;
- }
- case value_t::string:
- {
- m_value = *first.m_object->m_value.string;
- break;
- }
- case value_t::object:
- {
- m_value.object = create<object_t>(first.m_it.object_iterator,
- last.m_it.object_iterator);
- break;
- }
- case value_t::array:
- {
- m_value.array = create<array_t>(first.m_it.array_iterator,
- last.m_it.array_iterator);
- break;
- }
- case value_t::binary:
- {
- m_value = *first.m_object->m_value.binary;
- break;
- }
- case value_t::null:
- case value_t::discarded:
- default:
- JSON_THROW(invalid_iterator::create(206, detail::concat("cannot construct with iterators from ", first.m_object->type_name()), first.m_object));
- }
- set_parents();
- assert_invariant();
- }
- ///////////////////////////////////////
- // other constructors and destructor //
- ///////////////////////////////////////
- template<typename JsonRef,
- detail::enable_if_t<detail::conjunction<detail::is_json_ref<JsonRef>,
- std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 >
- basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {}
- /// @brief copy constructor
- /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
- basic_json(const basic_json& other)
- : json_base_class_t(other),
- m_type(other.m_type)
- {
- // check of passed value is valid
- other.assert_invariant();
- switch (m_type)
- {
- case value_t::object:
- {
- m_value = *other.m_value.object;
- break;
- }
- case value_t::array:
- {
- m_value = *other.m_value.array;
- break;
- }
- case value_t::string:
- {
- m_value = *other.m_value.string;
- break;
- }
- case value_t::boolean:
- {
- m_value = other.m_value.boolean;
- break;
- }
- case value_t::number_integer:
- {
- m_value = other.m_value.number_integer;
- break;
- }
- case value_t::number_unsigned:
- {
- m_value = other.m_value.number_unsigned;
- break;
- }
- case value_t::number_float:
- {
- m_value = other.m_value.number_float;
- break;
- }
- case value_t::binary:
- {
- m_value = *other.m_value.binary;
- break;
- }
- case value_t::null:
- case value_t::discarded:
- default:
- break;
- }
- set_parents();
- assert_invariant();
- }
- /// @brief move constructor
- /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
- basic_json(basic_json&& other) noexcept
- : json_base_class_t(std::move(other)),
- m_type(std::move(other.m_type)),
- m_value(std::move(other.m_value))
- {
- // check that passed value is valid
- other.assert_invariant(false); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved)
- // invalidate payload
- other.m_type = value_t::null;
- other.m_value = {};
- set_parents();
- assert_invariant();
- }
- /// @brief copy assignment
- /// @sa https://json.nlohmann.me/api/basic_json/operator=/
- basic_json& operator=(basic_json other) noexcept (
- std::is_nothrow_move_constructible<value_t>::value&&
- std::is_nothrow_move_assignable<value_t>::value&&
- std::is_nothrow_move_constructible<json_value>::value&&
- std::is_nothrow_move_assignable<json_value>::value&&
- std::is_nothrow_move_assignable<json_base_class_t>::value
- )
- {
- // check that passed value is valid
- other.assert_invariant();
- using std::swap;
- swap(m_type, other.m_type);
- swap(m_value, other.m_value);
- json_base_class_t::operator=(std::move(other));
- set_parents();
- assert_invariant();
- return *this;
- }
- /// @brief destructor
- /// @sa https://json.nlohmann.me/api/basic_json/~basic_json/
- ~basic_json() noexcept
- {
- assert_invariant(false);
- m_value.destroy(m_type);
- }
- /// @}
- public:
- ///////////////////////
- // object inspection //
- ///////////////////////
- /// @name object inspection
- /// Functions to inspect the type of a JSON value.
- /// @{
- /// @brief serialization
- /// @sa https://json.nlohmann.me/api/basic_json/dump/
- string_t dump(const int indent = -1,
- const char indent_char = ' ',
- const bool ensure_ascii = false,
- const error_handler_t error_handler = error_handler_t::strict) const
- {
- string_t result;
- serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
- if (indent >= 0)
- {
- s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
- }
- else
- {
- s.dump(*this, false, ensure_ascii, 0);
- }
- return result;
- }
- /// @brief return the type of the JSON value (explicit)
- /// @sa https://json.nlohmann.me/api/basic_json/type/
- constexpr value_t type() const noexcept
- {
- return m_type;
- }
- /// @brief return whether type is primitive
- /// @sa https://json.nlohmann.me/api/basic_json/is_primitive/
- constexpr bool is_primitive() const noexcept
- {
- return is_null() || is_string() || is_boolean() || is_number() || is_binary();
- }
- /// @brief return whether type is structured
- /// @sa https://json.nlohmann.me/api/basic_json/is_structured/
- constexpr bool is_structured() const noexcept
- {
- return is_array() || is_object();
- }
- /// @brief return whether value is null
- /// @sa https://json.nlohmann.me/api/basic_json/is_null/
- constexpr bool is_null() const noexcept
- {
- return m_type == value_t::null;
- }
- /// @brief return whether value is a boolean
- /// @sa https://json.nlohmann.me/api/basic_json/is_boolean/
- constexpr bool is_boolean() const noexcept
- {
- return m_type == value_t::boolean;
- }
- /// @brief return whether value is a number
- /// @sa https://json.nlohmann.me/api/basic_json/is_number/
- constexpr bool is_number() const noexcept
- {
- return is_number_integer() || is_number_float();
- }
- /// @brief return whether value is an integer number
- /// @sa https://json.nlohmann.me/api/basic_json/is_number_integer/
- constexpr bool is_number_integer() const noexcept
- {
- return m_type == value_t::number_integer || m_type == value_t::number_unsigned;
- }
- /// @brief return whether value is an unsigned integer number
- /// @sa https://json.nlohmann.me/api/basic_json/is_number_unsigned/
- constexpr bool is_number_unsigned() const noexcept
- {
- return m_type == value_t::number_unsigned;
- }
- /// @brief return whether value is a floating-point number
- /// @sa https://json.nlohmann.me/api/basic_json/is_number_float/
- constexpr bool is_number_float() const noexcept
- {
- return m_type == value_t::number_float;
- }
- /// @brief return whether value is an object
- /// @sa https://json.nlohmann.me/api/basic_json/is_object/
- constexpr bool is_object() const noexcept
- {
- return m_type == value_t::object;
- }
- /// @brief return whether value is an array
- /// @sa https://json.nlohmann.me/api/basic_json/is_array/
- constexpr bool is_array() const noexcept
- {
- return m_type == value_t::array;
- }
- /// @brief return whether value is a string
- /// @sa https://json.nlohmann.me/api/basic_json/is_string/
- constexpr bool is_string() const noexcept
- {
- return m_type == value_t::string;
- }
- /// @brief return whether value is a binary array
- /// @sa https://json.nlohmann.me/api/basic_json/is_binary/
- constexpr bool is_binary() const noexcept
- {
- return m_type == value_t::binary;
- }
- /// @brief return whether value is discarded
- /// @sa https://json.nlohmann.me/api/basic_json/is_discarded/
- constexpr bool is_discarded() const noexcept
- {
- return m_type == value_t::discarded;
- }
- /// @brief return the type of the JSON value (implicit)
- /// @sa https://json.nlohmann.me/api/basic_json/operator_value_t/
- constexpr operator value_t() const noexcept
- {
- return m_type;
- }
- /// @}
- private:
- //////////////////
- // value access //
- //////////////////
- /// get a boolean (explicit)
- boolean_t get_impl(boolean_t* /*unused*/) const
- {
- if (JSON_HEDLEY_LIKELY(is_boolean()))
- {
- return m_value.boolean;
- }
- JSON_THROW(type_error::create(302, detail::concat("type must be boolean, but is ", type_name()), this));
- }
- /// get a pointer to the value (object)
- object_t* get_impl_ptr(object_t* /*unused*/) noexcept
- {
- return is_object() ? m_value.object : nullptr;
- }
- /// get a pointer to the value (object)
- constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
- {
- return is_object() ? m_value.object : nullptr;
- }
- /// get a pointer to the value (array)
- array_t* get_impl_ptr(array_t* /*unused*/) noexcept
- {
- return is_array() ? m_value.array : nullptr;
- }
- /// get a pointer to the value (array)
- constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
- {
- return is_array() ? m_value.array : nullptr;
- }
- /// get a pointer to the value (string)
- string_t* get_impl_ptr(string_t* /*unused*/) noexcept
- {
- return is_string() ? m_value.string : nullptr;
- }
- /// get a pointer to the value (string)
- constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
- {
- return is_string() ? m_value.string : nullptr;
- }
- /// get a pointer to the value (boolean)
- boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
- {
- return is_boolean() ? &m_value.boolean : nullptr;
- }
- /// get a pointer to the value (boolean)
- constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
- {
- return is_boolean() ? &m_value.boolean : nullptr;
- }
- /// get a pointer to the value (integer number)
- number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
- {
- return is_number_integer() ? &m_value.number_integer : nullptr;
- }
- /// get a pointer to the value (integer number)
- constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
- {
- return is_number_integer() ? &m_value.number_integer : nullptr;
- }
- /// get a pointer to the value (unsigned number)
- number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
- {
- return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
- }
- /// get a pointer to the value (unsigned number)
- constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
- {
- return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
- }
- /// get a pointer to the value (floating-point number)
- number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
- {
- return is_number_float() ? &m_value.number_float : nullptr;
- }
- /// get a pointer to the value (floating-point number)
- constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
- {
- return is_number_float() ? &m_value.number_float : nullptr;
- }
- /// get a pointer to the value (binary)
- binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept
- {
- return is_binary() ? m_value.binary : nullptr;
- }
- /// get a pointer to the value (binary)
- constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept
- {
- return is_binary() ? m_value.binary : nullptr;
- }
- /*!
- @brief helper function to implement get_ref()
- This function helps to implement get_ref() without code duplication for
- const and non-const overloads
- @tparam ThisType will be deduced as `basic_json` or `const basic_json`
- @throw type_error.303 if ReferenceType does not match underlying value
- type of the current JSON
- */
- template<typename ReferenceType, typename ThisType>
- static ReferenceType get_ref_impl(ThisType& obj)
- {
- // delegate the call to get_ptr<>()
- auto* ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
- if (JSON_HEDLEY_LIKELY(ptr != nullptr))
- {
- return *ptr;
- }
- JSON_THROW(type_error::create(303, detail::concat("incompatible ReferenceType for get_ref, actual type is ", obj.type_name()), &obj));
- }
- public:
- /// @name value access
- /// Direct access to the stored value of a JSON value.
- /// @{
- /// @brief get a pointer value (implicit)
- /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/
- template<typename PointerType, typename std::enable_if<
- std::is_pointer<PointerType>::value, int>::type = 0>
- auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
- {
- // delegate the call to get_impl_ptr<>()
- return get_impl_ptr(static_cast<PointerType>(nullptr));
- }
- /// @brief get a pointer value (implicit)
- /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/
- template < typename PointerType, typename std::enable_if <
- std::is_pointer<PointerType>::value&&
- std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 >
- constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
- {
- // delegate the call to get_impl_ptr<>() const
- return get_impl_ptr(static_cast<PointerType>(nullptr));
- }
- private:
- /*!
- @brief get a value (explicit)
- Explicit type conversion between the JSON value and a compatible value
- which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
- and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
- The value is converted by calling the @ref json_serializer<ValueType>
- `from_json()` method.
- The function is equivalent to executing
- @code {.cpp}
- ValueType ret;
- JSONSerializer<ValueType>::from_json(*this, ret);
- return ret;
- @endcode
- This overloads is chosen if:
- - @a ValueType is not @ref basic_json,
- - @ref json_serializer<ValueType> has a `from_json()` method of the form
- `void from_json(const basic_json&, ValueType&)`, and
- - @ref json_serializer<ValueType> does not have a `from_json()` method of
- the form `ValueType from_json(const basic_json&)`
- @tparam ValueType the returned value type
- @return copy of the JSON value, converted to @a ValueType
- @throw what @ref json_serializer<ValueType> `from_json()` method throws
- @liveexample{The example below shows several conversions from JSON values
- to other types. There a few things to note: (1) Floating-point numbers can
- be converted to integers\, (2) A JSON array can be converted to a standard
- `std::vector<short>`\, (3) A JSON object can be converted to C++
- associative containers such as `std::unordered_map<std::string\,
- json>`.,get__ValueType_const}
- @since version 2.1.0
- */
- template < typename ValueType,
- detail::enable_if_t <
- detail::is_default_constructible<ValueType>::value&&
- detail::has_from_json<basic_json_t, ValueType>::value,
- int > = 0 >
- ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept(
- JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
- {
- auto ret = ValueType();
- JSONSerializer<ValueType>::from_json(*this, ret);
- return ret;
- }
- /*!
- @brief get a value (explicit); special case
- Explicit type conversion between the JSON value and a compatible value
- which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
- and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
- The value is converted by calling the @ref json_serializer<ValueType>
- `from_json()` method.
- The function is equivalent to executing
- @code {.cpp}
- return JSONSerializer<ValueType>::from_json(*this);
- @endcode
- This overloads is chosen if:
- - @a ValueType is not @ref basic_json and
- - @ref json_serializer<ValueType> has a `from_json()` method of the form
- `ValueType from_json(const basic_json&)`
- @note If @ref json_serializer<ValueType> has both overloads of
- `from_json()`, this one is chosen.
- @tparam ValueType the returned value type
- @return copy of the JSON value, converted to @a ValueType
- @throw what @ref json_serializer<ValueType> `from_json()` method throws
- @since version 2.1.0
- */
- template < typename ValueType,
- detail::enable_if_t <
- detail::has_non_default_from_json<basic_json_t, ValueType>::value,
- int > = 0 >
- ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept(
- JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
- {
- return JSONSerializer<ValueType>::from_json(*this);
- }
- /*!
- @brief get special-case overload
- This overloads converts the current @ref basic_json in a different
- @ref basic_json type
- @tparam BasicJsonType == @ref basic_json
- @return a copy of *this, converted into @a BasicJsonType
- @complexity Depending on the implementation of the called `from_json()`
- method.
- @since version 3.2.0
- */
- template < typename BasicJsonType,
- detail::enable_if_t <
- detail::is_basic_json<BasicJsonType>::value,
- int > = 0 >
- BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const
- {
- return *this;
- }
- /*!
- @brief get special-case overload
- This overloads avoids a lot of template boilerplate, it can be seen as the
- identity method
- @tparam BasicJsonType == @ref basic_json
- @return a copy of *this
- @complexity Constant.
- @since version 2.1.0
- */
- template<typename BasicJsonType,
- detail::enable_if_t<
- std::is_same<BasicJsonType, basic_json_t>::value,
- int> = 0>
- basic_json get_impl(detail::priority_tag<3> /*unused*/) const
- {
- return *this;
- }
- /*!
- @brief get a pointer value (explicit)
- @copydoc get()
- */
- template<typename PointerType,
- detail::enable_if_t<
- std::is_pointer<PointerType>::value,
- int> = 0>
- constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept
- -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
- {
- // delegate the call to get_ptr
- return get_ptr<PointerType>();
- }
- public:
- /*!
- @brief get a (pointer) value (explicit)
- Performs explicit type conversion between the JSON value and a compatible value if required.
- - If the requested type is a pointer to the internally stored JSON value that pointer is returned.
- No copies are made.
- - If the requested type is the current @ref basic_json, or a different @ref basic_json convertible
- from the current @ref basic_json.
- - Otherwise the value is converted by calling the @ref json_serializer<ValueType> `from_json()`
- method.
- @tparam ValueTypeCV the provided value type
- @tparam ValueType the returned value type
- @return copy of the JSON value, converted to @tparam ValueType if necessary
- @throw what @ref json_serializer<ValueType> `from_json()` method throws if conversion is required
- @since version 2.1.0
- */
- template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>>
- #if defined(JSON_HAS_CPP_14)
- constexpr
- #endif
- auto get() const noexcept(
- noexcept(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {})))
- -> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {}))
- {
- // we cannot static_assert on ValueTypeCV being non-const, because
- // there is support for get<const basic_json_t>(), which is why we
- // still need the uncvref
- static_assert(!std::is_reference<ValueTypeCV>::value,
- "get() cannot be used with reference types, you might want to use get_ref()");
- return get_impl<ValueType>(detail::priority_tag<4> {});
- }
- /*!
- @brief get a pointer value (explicit)
- Explicit pointer access to the internally stored JSON value. No copies are
- made.
- @warning The pointer becomes invalid if the underlying JSON object
- changes.
- @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
- object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
- @ref number_unsigned_t, or @ref number_float_t.
- @return pointer to the internally stored JSON value if the requested
- pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
- @complexity Constant.
- @liveexample{The example below shows how pointers to internal values of a
- JSON value can be requested. Note that no type conversions are made and a
- `nullptr` is returned if the value and the requested pointer type does not
- match.,get__PointerType}
- @sa see @ref get_ptr() for explicit pointer-member access
- @since version 1.0.0
- */
- template<typename PointerType, typename std::enable_if<
- std::is_pointer<PointerType>::value, int>::type = 0>
- auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
- {
- // delegate the call to get_ptr
- return get_ptr<PointerType>();
- }
- /// @brief get a value (explicit)
- /// @sa https://json.nlohmann.me/api/basic_json/get_to/
- template < typename ValueType,
- detail::enable_if_t <
- !detail::is_basic_json<ValueType>::value&&
- detail::has_from_json<basic_json_t, ValueType>::value,
- int > = 0 >
- ValueType & get_to(ValueType& v) const noexcept(noexcept(
- JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
- {
- JSONSerializer<ValueType>::from_json(*this, v);
- return v;
- }
- // specialization to allow calling get_to with a basic_json value
- // see https://github.com/nlohmann/json/issues/2175
- template<typename ValueType,
- detail::enable_if_t <
- detail::is_basic_json<ValueType>::value,
- int> = 0>
- ValueType & get_to(ValueType& v) const
- {
- v = *this;
- return v;
- }
- template <
- typename T, std::size_t N,
- typename Array = T (&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
- detail::enable_if_t <
- detail::has_from_json<basic_json_t, Array>::value, int > = 0 >
- Array get_to(T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
- noexcept(noexcept(JSONSerializer<Array>::from_json(
- std::declval<const basic_json_t&>(), v)))
- {
- JSONSerializer<Array>::from_json(*this, v);
- return v;
- }
- /// @brief get a reference value (implicit)
- /// @sa https://json.nlohmann.me/api/basic_json/get_ref/
- template<typename ReferenceType, typename std::enable_if<
- std::is_reference<ReferenceType>::value, int>::type = 0>
- ReferenceType get_ref()
- {
- // delegate call to get_ref_impl
- return get_ref_impl<ReferenceType>(*this);
- }
- /// @brief get a reference value (implicit)
- /// @sa https://json.nlohmann.me/api/basic_json/get_ref/
- template < typename ReferenceType, typename std::enable_if <
- std::is_reference<ReferenceType>::value&&
- std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int >::type = 0 >
- ReferenceType get_ref() const
- {
- // delegate call to get_ref_impl
- return get_ref_impl<ReferenceType>(*this);
- }
- /*!
- @brief get a value (implicit)
- Implicit type conversion between the JSON value and a compatible value.
- The call is realized by calling @ref get() const.
- @tparam ValueType non-pointer type compatible to the JSON value, for
- instance `int` for JSON integer numbers, `bool` for JSON booleans, or
- `std::vector` types for JSON arrays. The character type of @ref string_t
- as well as an initializer list of this type is excluded to avoid
- ambiguities as these types implicitly convert to `std::string`.
- @return copy of the JSON value, converted to type @a ValueType
- @throw type_error.302 in case passed type @a ValueType is incompatible
- to the JSON value type (e.g., the JSON value is of type boolean, but a
- string is requested); see example below
- @complexity Linear in the size of the JSON value.
- @liveexample{The example below shows several conversions from JSON values
- to other types. There a few things to note: (1) Floating-point numbers can
- be converted to integers\, (2) A JSON array can be converted to a standard
- `std::vector<short>`\, (3) A JSON object can be converted to C++
- associative containers such as `std::unordered_map<std::string\,
- json>`.,operator__ValueType}
- @since version 1.0.0
- */
- template < typename ValueType, typename std::enable_if <
- detail::conjunction <
- detail::negation<std::is_pointer<ValueType>>,
- detail::negation<std::is_same<ValueType, std::nullptr_t>>,
- detail::negation<std::is_same<ValueType, detail::json_ref<basic_json>>>,
- detail::negation<std::is_same<ValueType, typename string_t::value_type>>,
- detail::negation<detail::is_basic_json<ValueType>>,
- detail::negation<std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>>,
- #if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
- detail::negation<std::is_same<ValueType, std::string_view>>,
- #endif
- #if defined(JSON_HAS_CPP_17)
- detail::negation<std::is_same<ValueType, std::any>>,
- #endif
- detail::is_detected_lazy<detail::get_template_function, const basic_json_t&, ValueType>
- >::value, int >::type = 0 >
- JSON_EXPLICIT operator ValueType() const
- {
- // delegate the call to get<>() const
- return get<ValueType>();
- }
- /// @brief get a binary value
- /// @sa https://json.nlohmann.me/api/basic_json/get_binary/
- binary_t& get_binary()
- {
- if (!is_binary())
- {
- JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
- }
- return *get_ptr<binary_t*>();
- }
- /// @brief get a binary value
- /// @sa https://json.nlohmann.me/api/basic_json/get_binary/
- const binary_t& get_binary() const
- {
- if (!is_binary())
- {
- JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
- }
- return *get_ptr<const binary_t*>();
- }
- /// @}
- ////////////////////
- // element access //
- ////////////////////
- /// @name element access
- /// Access to the JSON value.
- /// @{
- /// @brief access specified array element with bounds checking
- /// @sa https://json.nlohmann.me/api/basic_json/at/
- reference at(size_type idx)
- {
- // at only works for arrays
- if (JSON_HEDLEY_LIKELY(is_array()))
- {
- JSON_TRY
- {
- return set_parent(m_value.array->at(idx));
- }
- JSON_CATCH (std::out_of_range&)
- {
- // create better exception explanation
- JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
- }
- }
- else
- {
- JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
- }
- }
- /// @brief access specified array element with bounds checking
- /// @sa https://json.nlohmann.me/api/basic_json/at/
- const_reference at(size_type idx) const
- {
- // at only works for arrays
- if (JSON_HEDLEY_LIKELY(is_array()))
- {
- JSON_TRY
- {
- return m_value.array->at(idx);
- }
- JSON_CATCH (std::out_of_range&)
- {
- // create better exception explanation
- JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
- }
- }
- else
- {
- JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
- }
- }
- /// @brief access specified object element with bounds checking
- /// @sa https://json.nlohmann.me/api/basic_json/at/
- reference at(const typename object_t::key_type& key)
- {
- // at only works for objects
- if (JSON_HEDLEY_UNLIKELY(!is_object()))
- {
- JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
- }
- auto it = m_value.object->find(key);
- if (it == m_value.object->end())
- {
- JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
- }
- return set_parent(it->second);
- }
- /// @brief access specified object element with bounds checking
- /// @sa https://json.nlohmann.me/api/basic_json/at/
- template<class KeyType, detail::enable_if_t<
- detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
- reference at(KeyType && key)
- {
- // at only works for objects
- if (JSON_HEDLEY_UNLIKELY(!is_object()))
- {
- JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
- }
- auto it = m_value.object->find(std::forward<KeyType>(key));
- if (it == m_value.object->end())
- {
- JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
- }
- return set_parent(it->second);
- }
- /// @brief access specified object element with bounds checking
- /// @sa https://json.nlohmann.me/api/basic_json/at/
- const_reference at(const typename object_t::key_type& key) const
- {
- // at only works for objects
- if (JSON_HEDLEY_UNLIKELY(!is_object()))
- {
- JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
- }
- auto it = m_value.object->find(key);
- if (it == m_value.object->end())
- {
- JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
- }
- return it->second;
- }
- /// @brief access specified object element with bounds checking
- /// @sa https://json.nlohmann.me/api/basic_json/at/
- template<class KeyType, detail::enable_if_t<
- detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
- const_reference at(KeyType && key) const
- {
- // at only works for objects
- if (JSON_HEDLEY_UNLIKELY(!is_object()))
- {
- JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
- }
- auto it = m_value.object->find(std::forward<KeyType>(key));
- if (it == m_value.object->end())
- {
- JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
- }
- return it->second;
- }
- /// @brief access specified array element
- /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
- reference operator[](size_type idx)
- {
- // implicitly convert null value to an empty array
- if (is_null())
- {
- m_type = value_t::array;
- m_value.array = create<array_t>();
- assert_invariant();
- }
- // operator[] only works for arrays
- if (JSON_HEDLEY_LIKELY(is_array()))
- {
- // fill up array with null values if given idx is outside range
- if (idx >= m_value.array->size())
- {
- #if JSON_DIAGNOSTICS
- // remember array size & capacity before resizing
- const auto old_size = m_value.array->size();
- const auto old_capacity = m_value.array->capacity();
- #endif
- m_value.array->resize(idx + 1);
- #if JSON_DIAGNOSTICS
- if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity))
- {
- // capacity has changed: update all parents
- set_parents();
- }
- else
- {
- // set parent for values added above
- set_parents(begin() + static_cast<typename iterator::difference_type>(old_size), static_cast<typename iterator::difference_type>(idx + 1 - old_size));
- }
- #endif
- assert_invariant();
- }
- return m_value.array->operator[](idx);
- }
- JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
- }
- /// @brief access specified array element
- /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
- const_reference operator[](size_type idx) const
- {
- // const operator[] only works for arrays
- if (JSON_HEDLEY_LIKELY(is_array()))
- {
- return m_value.array->operator[](idx);
- }
- JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
- }
- /// @brief access specified object element
- /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
- reference operator[](typename object_t::key_type key)
- {
- // implicitly convert null value to an empty object
- if (is_null())
- {
- m_type = value_t::object;
- m_value.object = create<object_t>();
- assert_invariant();
- }
- // operator[] only works for objects
- if (JSON_HEDLEY_LIKELY(is_object()))
- {
- auto result = m_value.object->emplace(std::move(key), nullptr);
- return set_parent(result.first->second);
- }
- JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
- }
- /// @brief access specified object element
- /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
- const_reference operator[](const typename object_t::key_type& key) const
- {
- // const operator[] only works for objects
- if (JSON_HEDLEY_LIKELY(is_object()))
- {
- auto it = m_value.object->find(key);
- JSON_ASSERT(it != m_value.object->end());
- return it->second;
- }
- JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
- }
- // these two functions resolve a (const) char * ambiguity affecting Clang and MSVC
- // (they seemingly cannot be constrained to resolve the ambiguity)
- template<typename T>
- reference operator[](T* key)
- {
- return operator[](typename object_t::key_type(key));
- }
- template<typename T>
- const_reference operator[](T* key) const
- {
- return operator[](typename object_t::key_type(key));
- }
- /// @brief access specified object element
- /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
- template<class KeyType, detail::enable_if_t<
- detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
- reference operator[](KeyType && key)
- {
- // implicitly convert null value to an empty object
- if (is_null())
- {
- m_type = value_t::object;
- m_value.object = create<object_t>();
- assert_invariant();
- }
- // operator[] only works for objects
- if (JSON_HEDLEY_LIKELY(is_object()))
- {
- auto result = m_value.object->emplace(std::forward<KeyType>(key), nullptr);
- return set_parent(result.first->second);
- }
- JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
- }
- /// @brief access specified object element
- /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
- template<class KeyType, detail::enable_if_t<
- detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
- const_reference operator[](KeyType && key) const
- {
- // const operator[] only works for objects
- if (JSON_HEDLEY_LIKELY(is_object()))
- {
- auto it = m_value.object->find(std::forward<KeyType>(key));
- JSON_ASSERT(it != m_value.object->end());
- return it->second;
- }
- JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
- }
- private:
- template<typename KeyType>
- using is_comparable_with_object_key = detail::is_comparable <
- object_comparator_t, const typename object_t::key_type&, KeyType >;
- template<typename ValueType>
- using value_return_type = std::conditional <
- detail::is_c_string_uncvref<ValueType>::value,
- string_t, typename std::decay<ValueType>::type >;
- public:
- /// @brief access specified object element with default value
- /// @sa https://json.nlohmann.me/api/basic_json/value/
- template < class ValueType, detail::enable_if_t <
- !detail::is_transparent<object_comparator_t>::value
- && detail::is_getable<basic_json_t, ValueType>::value
- && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
- ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
- {
- // value only works for objects
- if (JSON_HEDLEY_LIKELY(is_object()))
- {
- // if key is found, return value and given default value otherwise
- const auto it = find(key);
- if (it != end())
- {
- return it->template get<ValueType>();
- }
- return default_value;
- }
- JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
- }
- /// @brief access specified object element with default value
- /// @sa https://json.nlohmann.me/api/basic_json/value/
- template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
- detail::enable_if_t <
- !detail::is_transparent<object_comparator_t>::value
- && detail::is_getable<basic_json_t, ReturnType>::value
- && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
- ReturnType value(const typename object_t::key_type& key, ValueType && default_value) const
- {
- // value only works for objects
- if (JSON_HEDLEY_LIKELY(is_object()))
- {
- // if key is found, return value and given default value otherwise
- const auto it = find(key);
- if (it != end())
- {
- return it->template get<ReturnType>();
- }
- return std::forward<ValueType>(default_value);
- }
- JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
- }
- /// @brief access specified object element with default value
- /// @sa https://json.nlohmann.me/api/basic_json/value/
- template < class ValueType, class KeyType, detail::enable_if_t <
- detail::is_transparent<object_comparator_t>::value
- && !detail::is_json_pointer<KeyType>::value
- && is_comparable_with_object_key<KeyType>::value
- && detail::is_getable<basic_json_t, ValueType>::value
- && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
- ValueType value(KeyType && key, const ValueType& default_value) const
- {
- // value only works for objects
- if (JSON_HEDLEY_LIKELY(is_object()))
- {
- // if key is found, return value and given default value otherwise
- const auto it = find(std::forward<KeyType>(key));
- if (it != end())
- {
- return it->template get<ValueType>();
- }
- return default_value;
- }
- JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
- }
- /// @brief access specified object element via JSON Pointer with default value
- /// @sa https://json.nlohmann.me/api/basic_json/value/
- template < class ValueType, class KeyType, class ReturnType = typename value_return_type<ValueType>::type,
- detail::enable_if_t <
- detail::is_transparent<object_comparator_t>::value
- && !detail::is_json_pointer<KeyType>::value
- && is_comparable_with_object_key<KeyType>::value
- && detail::is_getable<basic_json_t, ReturnType>::value
- && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
- ReturnType value(KeyType && key, ValueType && default_value) const
- {
- // value only works for objects
- if (JSON_HEDLEY_LIKELY(is_object()))
- {
- // if key is found, return value and given default value otherwise
- const auto it = find(std::forward<KeyType>(key));
- if (it != end())
- {
- return it->template get<ReturnType>();
- }
- return std::forward<ValueType>(default_value);
- }
- JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
- }
- /// @brief access specified object element via JSON Pointer with default value
- /// @sa https://json.nlohmann.me/api/basic_json/value/
- template < class ValueType, detail::enable_if_t <
- detail::is_getable<basic_json_t, ValueType>::value
- && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
- ValueType value(const json_pointer& ptr, const ValueType& default_value) const
- {
- // value only works for objects
- if (JSON_HEDLEY_LIKELY(is_object()))
- {
- // if pointer resolves a value, return it or use default value
- JSON_TRY
- {
- return ptr.get_checked(this).template get<ValueType>();
- }
- JSON_INTERNAL_CATCH (out_of_range&)
- {
- return default_value;
- }
- }
- JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
- }
- /// @brief access specified object element via JSON Pointer with default value
- /// @sa https://json.nlohmann.me/api/basic_json/value/
- template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
- detail::enable_if_t <
- detail::is_getable<basic_json_t, ReturnType>::value
- && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
- ReturnType value(const json_pointer& ptr, ValueType && default_value) const
- {
- // value only works for objects
- if (JSON_HEDLEY_LIKELY(is_object()))
- {
- // if pointer resolves a value, return it or use default value
- JSON_TRY
- {
- return ptr.get_checked(this).template get<ReturnType>();
- }
- JSON_INTERNAL_CATCH (out_of_range&)
- {
- return std::forward<ValueType>(default_value);
- }
- }
- JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
- }
- template < class ValueType, class BasicJsonType, detail::enable_if_t <
- detail::is_basic_json<BasicJsonType>::value
- && detail::is_getable<basic_json_t, ValueType>::value
- && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
- JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
- ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const
- {
- return value(ptr.convert(), default_value);
- }
- template < class ValueType, class BasicJsonType, class ReturnType = typename value_return_type<ValueType>::type,
- detail::enable_if_t <
- detail::is_basic_json<BasicJsonType>::value
- && detail::is_getable<basic_json_t, ReturnType>::value
- && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
- JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
- ReturnType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType && default_value) const
- {
- return value(ptr.convert(), std::forward<ValueType>(default_value));
- }
- /// @brief access the first element
- /// @sa https://json.nlohmann.me/api/basic_json/front/
- reference front()
- {
- return *begin();
- }
- /// @brief access the first element
- /// @sa https://json.nlohmann.me/api/basic_json/front/
- const_reference front() const
- {
- return *cbegin();
- }
- /// @brief access the last element
- /// @sa https://json.nlohmann.me/api/basic_json/back/
- reference back()
- {
- auto tmp = end();
- --tmp;
- return *tmp;
- }
- /// @brief access the last element
- /// @sa https://json.nlohmann.me/api/basic_json/back/
- const_reference back() const
- {
- auto tmp = cend();
- --tmp;
- return *tmp;
- }
- /// @brief remove element given an iterator
- /// @sa https://json.nlohmann.me/api/basic_json/erase/
- template < class IteratorType, detail::enable_if_t <
- std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
- std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
- IteratorType erase(IteratorType pos)
- {
- // make sure iterator fits the current value
- if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
- {
- JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
- }
- IteratorType result = end();
- switch (m_type)
- {
- case value_t::boolean:
- case value_t::number_float:
- case value_t::number_integer:
- case value_t::number_unsigned:
- case value_t::string:
- case value_t::binary:
- {
- if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin()))
- {
- JSON_THROW(invalid_iterator::create(205, "iterator out of range", this));
- }
- if (is_string())
- {
- AllocatorType<string_t> alloc;
- std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
- std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
- m_value.string = nullptr;
- }
- else if (is_binary())
- {
- AllocatorType<binary_t> alloc;
- std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.binary);
- std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.binary, 1);
- m_value.binary = nullptr;
- }
- m_type = value_t::null;
- assert_invariant();
- break;
- }
- case value_t::object:
- {
- result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
- break;
- }
- case value_t::array:
- {
- result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
- break;
- }
- case value_t::null:
- case value_t::discarded:
- default:
- JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
- }
- return result;
- }
- /// @brief remove elements given an iterator range
- /// @sa https://json.nlohmann.me/api/basic_json/erase/
- template < class IteratorType, detail::enable_if_t <
- std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
- std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
- IteratorType erase(IteratorType first, IteratorType last)
- {
- // make sure iterator fits the current value
- if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object))
- {
- JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", this));
- }
- IteratorType result = end();
- switch (m_type)
- {
- case value_t::boolean:
- case value_t::number_float:
- case value_t::number_integer:
- case value_t::number_unsigned:
- case value_t::string:
- case value_t::binary:
- {
- if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
- || !last.m_it.primitive_iterator.is_end()))
- {
- JSON_THROW(invalid_iterator::create(204, "iterators out of range", this));
- }
- if (is_string())
- {
- AllocatorType<string_t> alloc;
- std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
- std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
- m_value.string = nullptr;
- }
- else if (is_binary())
- {
- AllocatorType<binary_t> alloc;
- std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.binary);
- std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.binary, 1);
- m_value.binary = nullptr;
- }
- m_type = value_t::null;
- assert_invariant();
- break;
- }
- case value_t::object:
- {
- result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
- last.m_it.object_iterator);
- break;
- }
- case value_t::array:
- {
- result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
- last.m_it.array_iterator);
- break;
- }
- case value_t::null:
- case value_t::discarded:
- default:
- JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
- }
- return result;
- }
- private:
- template < typename KeyType, detail::enable_if_t <
- detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
- size_type erase_internal(KeyType && key)
- {
- // this erase only works for objects
- if (JSON_HEDLEY_UNLIKELY(!is_object()))
- {
- JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
- }
- return m_value.object->erase(std::forward<KeyType>(key));
- }
- template < typename KeyType, detail::enable_if_t <
- !detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
- size_type erase_internal(KeyType && key)
- {
- // this erase only works for objects
- if (JSON_HEDLEY_UNLIKELY(!is_object()))
- {
- JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
- }
- const auto it = m_value.object->find(std::forward<KeyType>(key));
- if (it != m_value.object->end())
- {
- m_value.object->erase(it);
- return 1;
- }
- return 0;
- }
- public:
- /// @brief remove element from a JSON object given a key
- /// @sa https://json.nlohmann.me/api/basic_json/erase/
- size_type erase(const typename object_t::key_type& key)
- {
- // the indirection via erase_internal() is added to avoid making this
- // function a template and thus de-rank it during overload resolution
- return erase_internal(key);
- }
- /// @brief remove element from a JSON object given a key
- /// @sa https://json.nlohmann.me/api/basic_json/erase/
- template<class KeyType, detail::enable_if_t<
- detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
- size_type erase(KeyType && key)
- {
- return erase_internal(std::forward<KeyType>(key));
- }
- /// @brief remove element from a JSON array given an index
- /// @sa https://json.nlohmann.me/api/basic_json/erase/
- void erase(const size_type idx)
- {
- // this erase only works for arrays
- if (JSON_HEDLEY_LIKELY(is_array()))
- {
- if (JSON_HEDLEY_UNLIKELY(idx >= size()))
- {
- JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
- }
- m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
- }
- else
- {
- JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
- }
- }
- /// @}
- ////////////
- // lookup //
- ////////////
- /// @name lookup
- /// @{
- /// @brief find an element in a JSON object
- /// @sa https://json.nlohmann.me/api/basic_json/find/
- iterator find(const typename object_t::key_type& key)
- {
- auto result = end();
- if (is_object())
- {
- result.m_it.object_iterator = m_value.object->find(key);
- }
- return result;
- }
- /// @brief find an element in a JSON object
- /// @sa https://json.nlohmann.me/api/basic_json/find/
- const_iterator find(const typename object_t::key_type& key) const
- {
- auto result = cend();
- if (is_object())
- {
- result.m_it.object_iterator = m_value.object->find(key);
- }
- return result;
- }
- /// @brief find an element in a JSON object
- /// @sa https://json.nlohmann.me/api/basic_json/find/
- template<class KeyType, detail::enable_if_t<
- detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
- iterator find(KeyType && key)
- {
- auto result = end();
- if (is_object())
- {
- result.m_it.object_iterator = m_value.object->find(std::forward<KeyType>(key));
- }
- return result;
- }
- /// @brief find an element in a JSON object
- /// @sa https://json.nlohmann.me/api/basic_json/find/
- template<class KeyType, detail::enable_if_t<
- detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
- const_iterator find(KeyType && key) const
- {
- auto result = cend();
- if (is_object())
- {
- result.m_it.object_iterator = m_value.object->find(std::forward<KeyType>(key));
- }
- return result;
- }
- /// @brief returns the number of occurrences of a key in a JSON object
- /// @sa https://json.nlohmann.me/api/basic_json/count/
- size_type count(const typename object_t::key_type& key) const
- {
- // return 0 for all nonobject types
- return is_object() ? m_value.object->count(key) : 0;
- }
- /// @brief returns the number of occurrences of a key in a JSON object
- /// @sa https://json.nlohmann.me/api/basic_json/count/
- template<class KeyType, detail::enable_if_t<
- detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
- size_type count(KeyType && key) const
- {
- // return 0 for all nonobject types
- return is_object() ? m_value.object->count(std::forward<KeyType>(key)) : 0;
- }
- /// @brief check the existence of an element in a JSON object
- /// @sa https://json.nlohmann.me/api/basic_json/contains/
- bool contains(const typename object_t::key_type& key) const
- {
- return is_object() && m_value.object->find(key) != m_value.object->end();
- }
- /// @brief check the existence of an element in a JSON object
- /// @sa https://json.nlohmann.me/api/basic_json/contains/
- template<class KeyType, detail::enable_if_t<
- detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
- bool contains(KeyType && key) const
- {
- return is_object() && m_value.object->find(std::forward<KeyType>(key)) != m_value.object->end();
- }
- /// @brief check the existence of an element in a JSON object given a JSON pointer
- /// @sa https://json.nlohmann.me/api/basic_json/contains/
- bool contains(const json_pointer& ptr) const
- {
- return ptr.contains(this);
- }
- template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
- JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
- bool contains(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr) const
- {
- return ptr.contains(this);
- }
- /// @}
- ///////////////
- // iterators //
- ///////////////
- /// @name iterators
- /// @{
- /// @brief returns an iterator to the first element
- /// @sa https://json.nlohmann.me/api/basic_json/begin/
- iterator begin() noexcept
- {
- iterator result(this);
- result.set_begin();
- return result;
- }
- /// @brief returns an iterator to the first element
- /// @sa https://json.nlohmann.me/api/basic_json/begin/
- const_iterator begin() const noexcept
- {
- return cbegin();
- }
- /// @brief returns a const iterator to the first element
- /// @sa https://json.nlohmann.me/api/basic_json/cbegin/
- const_iterator cbegin() const noexcept
- {
- const_iterator result(this);
- result.set_begin();
- return result;
- }
- /// @brief returns an iterator to one past the last element
- /// @sa https://json.nlohmann.me/api/basic_json/end/
- iterator end() noexcept
- {
- iterator result(this);
- result.set_end();
- return result;
- }
- /// @brief returns an iterator to one past the last element
- /// @sa https://json.nlohmann.me/api/basic_json/end/
- const_iterator end() const noexcept
- {
- return cend();
- }
- /// @brief returns an iterator to one past the last element
- /// @sa https://json.nlohmann.me/api/basic_json/cend/
- const_iterator cend() const noexcept
- {
- const_iterator result(this);
- result.set_end();
- return result;
- }
- /// @brief returns an iterator to the reverse-beginning
- /// @sa https://json.nlohmann.me/api/basic_json/rbegin/
- reverse_iterator rbegin() noexcept
- {
- return reverse_iterator(end());
- }
- /// @brief returns an iterator to the reverse-beginning
- /// @sa https://json.nlohmann.me/api/basic_json/rbegin/
- const_reverse_iterator rbegin() const noexcept
- {
- return crbegin();
- }
- /// @brief returns an iterator to the reverse-end
- /// @sa https://json.nlohmann.me/api/basic_json/rend/
- reverse_iterator rend() noexcept
- {
- return reverse_iterator(begin());
- }
- /// @brief returns an iterator to the reverse-end
- /// @sa https://json.nlohmann.me/api/basic_json/rend/
- const_reverse_iterator rend() const noexcept
- {
- return crend();
- }
- /// @brief returns a const reverse iterator to the last element
- /// @sa https://json.nlohmann.me/api/basic_json/crbegin/
- const_reverse_iterator crbegin() const noexcept
- {
- return const_reverse_iterator(cend());
- }
- /// @brief returns a const reverse iterator to one before the first
- /// @sa https://json.nlohmann.me/api/basic_json/crend/
- const_reverse_iterator crend() const noexcept
- {
- return const_reverse_iterator(cbegin());
- }
- public:
- /// @brief wrapper to access iterator member functions in range-based for
- /// @sa https://json.nlohmann.me/api/basic_json/items/
- /// @deprecated This function is deprecated since 3.1.0 and will be removed in
- /// version 4.0.0 of the library. Please use @ref items() instead;
- /// that is, replace `json::iterator_wrapper(j)` with `j.items()`.
- JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
- static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
- {
- return ref.items();
- }
- /// @brief wrapper to access iterator member functions in range-based for
- /// @sa https://json.nlohmann.me/api/basic_json/items/
- /// @deprecated This function is deprecated since 3.1.0 and will be removed in
- /// version 4.0.0 of the library. Please use @ref items() instead;
- /// that is, replace `json::iterator_wrapper(j)` with `j.items()`.
- JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
- static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
- {
- return ref.items();
- }
- /// @brief helper to access iterator member functions in range-based for
- /// @sa https://json.nlohmann.me/api/basic_json/items/
- iteration_proxy<iterator> items() noexcept
- {
- return iteration_proxy<iterator>(*this);
- }
- /// @brief helper to access iterator member functions in range-based for
- /// @sa https://json.nlohmann.me/api/basic_json/items/
- iteration_proxy<const_iterator> items() const noexcept
- {
- return iteration_proxy<const_iterator>(*this);
- }
- /// @}
- //////////////
- // capacity //
- //////////////
- /// @name capacity
- /// @{
- /// @brief checks whether the container is empty.
- /// @sa https://json.nlohmann.me/api/basic_json/empty/
- bool empty() const noexcept
- {
- switch (m_type)
- {
- case value_t::null:
- {
- // null values are empty
- return true;
- }
- case value_t::array:
- {
- // delegate call to array_t::empty()
- return m_value.array->empty();
- }
- case value_t::object:
- {
- // delegate call to object_t::empty()
- return m_value.object->empty();
- }
- case value_t::string:
- case value_t::boolean:
- case value_t::number_integer:
- case value_t::number_unsigned:
- case value_t::number_float:
- case value_t::binary:
- case value_t::discarded:
- default:
- {
- // all other types are nonempty
- return false;
- }
- }
- }
- /// @brief returns the number of elements
- /// @sa https://json.nlohmann.me/api/basic_json/size/
- size_type size() const noexcept
- {
- switch (m_type)
- {
- case value_t::null:
- {
- // null values are empty
- return 0;
- }
- case value_t::array:
- {
- // delegate call to array_t::size()
- return m_value.array->size();
- }
- case value_t::object:
- {
- // delegate call to object_t::size()
- return m_value.object->size();
- }
- case value_t::string:
- case value_t::boolean:
- case value_t::number_integer:
- case value_t::number_unsigned:
- case value_t::number_float:
- case value_t::binary:
- case value_t::discarded:
- default:
- {
- // all other types have size 1
- return 1;
- }
- }
- }
- /// @brief returns the maximum possible number of elements
- /// @sa https://json.nlohmann.me/api/basic_json/max_size/
- size_type max_size() const noexcept
- {
- switch (m_type)
- {
- case value_t::array:
- {
- // delegate call to array_t::max_size()
- return m_value.array->max_size();
- }
- case value_t::object:
- {
- // delegate call to object_t::max_size()
- return m_value.object->max_size();
- }
- case value_t::null:
- case value_t::string:
- case value_t::boolean:
- case value_t::number_integer:
- case value_t::number_unsigned:
- case value_t::number_float:
- case value_t::binary:
- case value_t::discarded:
- default:
- {
- // all other types have max_size() == size()
- return size();
- }
- }
- }
- /// @}
- ///////////////
- // modifiers //
- ///////////////
- /// @name modifiers
- /// @{
- /// @brief clears the contents
- /// @sa https://json.nlohmann.me/api/basic_json/clear/
- void clear() noexcept
- {
- switch (m_type)
- {
- case value_t::number_integer:
- {
- m_value.number_integer = 0;
- break;
- }
- case value_t::number_unsigned:
- {
- m_value.number_unsigned = 0;
- break;
- }
- case value_t::number_float:
- {
- m_value.number_float = 0.0;
- break;
- }
- case value_t::boolean:
- {
- m_value.boolean = false;
- break;
- }
- case value_t::string:
- {
- m_value.string->clear();
- break;
- }
- case value_t::binary:
- {
- m_value.binary->clear();
- break;
- }
- case value_t::array:
- {
- m_value.array->clear();
- break;
- }
- case value_t::object:
- {
- m_value.object->clear();
- break;
- }
- case value_t::null:
- case value_t::discarded:
- default:
- break;
- }
- }
- /// @brief add an object to an array
- /// @sa https://json.nlohmann.me/api/basic_json/push_back/
- void push_back(basic_json&& val)
- {
- // push_back only works for null objects or arrays
- if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
- {
- JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
- }
- // transform null object into an array
- if (is_null())
- {
- m_type = value_t::array;
- m_value = value_t::array;
- assert_invariant();
- }
- // add element to array (move semantics)
- const auto old_capacity = m_value.array->capacity();
- m_value.array->push_back(std::move(val));
- set_parent(m_value.array->back(), old_capacity);
- // if val is moved from, basic_json move constructor marks it null, so we do not call the destructor
- }
- /// @brief add an object to an array
- /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
- reference operator+=(basic_json&& val)
- {
- push_back(std::move(val));
- return *this;
- }
- /// @brief add an object to an array
- /// @sa https://json.nlohmann.me/api/basic_json/push_back/
- void push_back(const basic_json& val)
- {
- // push_back only works for null objects or arrays
- if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
- {
- JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
- }
- // transform null object into an array
- if (is_null())
- {
- m_type = value_t::array;
- m_value = value_t::array;
- assert_invariant();
- }
- // add element to array
- const auto old_capacity = m_value.array->capacity();
- m_value.array->push_back(val);
- set_parent(m_value.array->back(), old_capacity);
- }
- /// @brief add an object to an array
- /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
- reference operator+=(const basic_json& val)
- {
- push_back(val);
- return *this;
- }
- /// @brief add an object to an object
- /// @sa https://json.nlohmann.me/api/basic_json/push_back/
- void push_back(const typename object_t::value_type& val)
- {
- // push_back only works for null objects or objects
- if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
- {
- JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
- }
- // transform null object into an object
- if (is_null())
- {
- m_type = value_t::object;
- m_value = value_t::object;
- assert_invariant();
- }
- // add element to object
- auto res = m_value.object->insert(val);
- set_parent(res.first->second);
- }
- /// @brief add an object to an object
- /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
- reference operator+=(const typename object_t::value_type& val)
- {
- push_back(val);
- return *this;
- }
- /// @brief add an object to an object
- /// @sa https://json.nlohmann.me/api/basic_json/push_back/
- void push_back(initializer_list_t init)
- {
- if (is_object() && init.size() == 2 && (*init.begin())->is_string())
- {
- basic_json&& key = init.begin()->moved_or_copied();
- push_back(typename object_t::value_type(
- std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
- }
- else
- {
- push_back(basic_json(init));
- }
- }
- /// @brief add an object to an object
- /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
- reference operator+=(initializer_list_t init)
- {
- push_back(init);
- return *this;
- }
- /// @brief add an object to an array
- /// @sa https://json.nlohmann.me/api/basic_json/emplace_back/
- template<class... Args>
- reference emplace_back(Args&& ... args)
- {
- // emplace_back only works for null objects or arrays
- if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
- {
- JSON_THROW(type_error::create(311, detail::concat("cannot use emplace_back() with ", type_name()), this));
- }
- // transform null object into an array
- if (is_null())
- {
- m_type = value_t::array;
- m_value = value_t::array;
- assert_invariant();
- }
- // add element to array (perfect forwarding)
- const auto old_capacity = m_value.array->capacity();
- m_value.array->emplace_back(std::forward<Args>(args)...);
- return set_parent(m_value.array->back(), old_capacity);
- }
- /// @brief add an object to an object if key does not exist
- /// @sa https://json.nlohmann.me/api/basic_json/emplace/
- template<class... Args>
- std::pair<iterator, bool> emplace(Args&& ... args)
- {
- // emplace only works for null objects or arrays
- if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
- {
- JSON_THROW(type_error::create(311, detail::concat("cannot use emplace() with ", type_name()), this));
- }
- // transform null object into an object
- if (is_null())
- {
- m_type = value_t::object;
- m_value = value_t::object;
- assert_invariant();
- }
- // add element to array (perfect forwarding)
- auto res = m_value.object->emplace(std::forward<Args>(args)...);
- set_parent(res.first->second);
- // create result iterator and set iterator to the result of emplace
- auto it = begin();
- it.m_it.object_iterator = res.first;
- // return pair of iterator and boolean
- return {it, res.second};
- }
- /// Helper for insertion of an iterator
- /// @note: This uses std::distance to support GCC 4.8,
- /// see https://github.com/nlohmann/json/pull/1257
- template<typename... Args>
- iterator insert_iterator(const_iterator pos, Args&& ... args)
- {
- iterator result(this);
- JSON_ASSERT(m_value.array != nullptr);
- auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator);
- m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
- result.m_it.array_iterator = m_value.array->begin() + insert_pos;
- // This could have been written as:
- // result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
- // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
- set_parents();
- return result;
- }
- /// @brief inserts element into array
- /// @sa https://json.nlohmann.me/api/basic_json/insert/
- iterator insert(const_iterator pos, const basic_json& val)
- {
- // insert only works for arrays
- if (JSON_HEDLEY_LIKELY(is_array()))
- {
- // check if iterator pos fits to this JSON value
- if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
- {
- JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
- }
- // insert to array and return iterator
- return insert_iterator(pos, val);
- }
- JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
- }
- /// @brief inserts element into array
- /// @sa https://json.nlohmann.me/api/basic_json/insert/
- iterator insert(const_iterator pos, basic_json&& val)
- {
- return insert(pos, val);
- }
- /// @brief inserts copies of element into array
- /// @sa https://json.nlohmann.me/api/basic_json/insert/
- iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
- {
- // insert only works for arrays
- if (JSON_HEDLEY_LIKELY(is_array()))
- {
- // check if iterator pos fits to this JSON value
- if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
- {
- JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
- }
- // insert to array and return iterator
- return insert_iterator(pos, cnt, val);
- }
- JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
- }
- /// @brief inserts range of elements into array
- /// @sa https://json.nlohmann.me/api/basic_json/insert/
- iterator insert(const_iterator pos, const_iterator first, const_iterator last)
- {
- // insert only works for arrays
- if (JSON_HEDLEY_UNLIKELY(!is_array()))
- {
- JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
- }
- // check if iterator pos fits to this JSON value
- if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
- {
- JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
- }
- // check if range iterators belong to the same JSON object
- if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
- {
- JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
- }
- if (JSON_HEDLEY_UNLIKELY(first.m_object == this))
- {
- JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", this));
- }
- // insert to array and return iterator
- return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
- }
- /// @brief inserts elements from initializer list into array
- /// @sa https://json.nlohmann.me/api/basic_json/insert/
- iterator insert(const_iterator pos, initializer_list_t ilist)
- {
- // insert only works for arrays
- if (JSON_HEDLEY_UNLIKELY(!is_array()))
- {
- JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
- }
- // check if iterator pos fits to this JSON value
- if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
- {
- JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
- }
- // insert to array and return iterator
- return insert_iterator(pos, ilist.begin(), ilist.end());
- }
- /// @brief inserts range of elements into object
- /// @sa https://json.nlohmann.me/api/basic_json/insert/
- void insert(const_iterator first, const_iterator last)
- {
- // insert only works for objects
- if (JSON_HEDLEY_UNLIKELY(!is_object()))
- {
- JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
- }
- // check if range iterators belong to the same JSON object
- if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
- {
- JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
- }
- // passed iterators must belong to objects
- if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
- {
- JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", this));
- }
- m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
- }
- /// @brief updates a JSON object from another object, overwriting existing keys
- /// @sa https://json.nlohmann.me/api/basic_json/update/
- void update(const_reference j, bool merge_objects = false)
- {
- update(j.begin(), j.end(), merge_objects);
- }
- /// @brief updates a JSON object from another object, overwriting existing keys
- /// @sa https://json.nlohmann.me/api/basic_json/update/
- void update(const_iterator first, const_iterator last, bool merge_objects = false)
- {
- // implicitly convert null value to an empty object
- if (is_null())
- {
- m_type = value_t::object;
- m_value.object = create<object_t>();
- assert_invariant();
- }
- if (JSON_HEDLEY_UNLIKELY(!is_object()))
- {
- JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", type_name()), this));
- }
- // check if range iterators belong to the same JSON object
- if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
- {
- JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
- }
- // passed iterators must belong to objects
- if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
- {
- JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", first.m_object->type_name()), first.m_object));
- }
- for (auto it = first; it != last; ++it)
- {
- if (merge_objects && it.value().is_object())
- {
- auto it2 = m_value.object->find(it.key());
- if (it2 != m_value.object->end())
- {
- it2->second.update(it.value(), true);
- continue;
- }
- }
- m_value.object->operator[](it.key()) = it.value();
- #if JSON_DIAGNOSTICS
- m_value.object->operator[](it.key()).m_parent = this;
- #endif
- }
- }
- /// @brief exchanges the values
- /// @sa https://json.nlohmann.me/api/basic_json/swap/
- void swap(reference other) noexcept (
- std::is_nothrow_move_constructible<value_t>::value&&
- std::is_nothrow_move_assignable<value_t>::value&&
- std::is_nothrow_move_constructible<json_value>::value&&
- std::is_nothrow_move_assignable<json_value>::value
- )
- {
- std::swap(m_type, other.m_type);
- std::swap(m_value, other.m_value);
- set_parents();
- other.set_parents();
- assert_invariant();
- }
- /// @brief exchanges the values
- /// @sa https://json.nlohmann.me/api/basic_json/swap/
- friend void swap(reference left, reference right) noexcept (
- std::is_nothrow_move_constructible<value_t>::value&&
- std::is_nothrow_move_assignable<value_t>::value&&
- std::is_nothrow_move_constructible<json_value>::value&&
- std::is_nothrow_move_assignable<json_value>::value
- )
- {
- left.swap(right);
- }
- /// @brief exchanges the values
- /// @sa https://json.nlohmann.me/api/basic_json/swap/
- void swap(array_t& other) // NOLINT(bugprone-exception-escape)
- {
- // swap only works for arrays
- if (JSON_HEDLEY_LIKELY(is_array()))
- {
- using std::swap;
- swap(*(m_value.array), other);
- }
- else
- {
- JSON_THROW(type_error::create(310, detail::concat("cannot use swap(array_t&) with ", type_name()), this));
- }
- }
- /// @brief exchanges the values
- /// @sa https://json.nlohmann.me/api/basic_json/swap/
- void swap(object_t& other) // NOLINT(bugprone-exception-escape)
- {
- // swap only works for objects
- if (JSON_HEDLEY_LIKELY(is_object()))
- {
- using std::swap;
- swap(*(m_value.object), other);
- }
- else
- {
- JSON_THROW(type_error::create(310, detail::concat("cannot use swap(object_t&) with ", type_name()), this));
- }
- }
- /// @brief exchanges the values
- /// @sa https://json.nlohmann.me/api/basic_json/swap/
- void swap(string_t& other) // NOLINT(bugprone-exception-escape)
- {
- // swap only works for strings
- if (JSON_HEDLEY_LIKELY(is_string()))
- {
- using std::swap;
- swap(*(m_value.string), other);
- }
- else
- {
- JSON_THROW(type_error::create(310, detail::concat("cannot use swap(string_t&) with ", type_name()), this));
- }
- }
- /// @brief exchanges the values
- /// @sa https://json.nlohmann.me/api/basic_json/swap/
- void swap(binary_t& other) // NOLINT(bugprone-exception-escape)
- {
- // swap only works for strings
- if (JSON_HEDLEY_LIKELY(is_binary()))
- {
- using std::swap;
- swap(*(m_value.binary), other);
- }
- else
- {
- JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t&) with ", type_name()), this));
- }
- }
- /// @brief exchanges the values
- /// @sa https://json.nlohmann.me/api/basic_json/swap/
- void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape)
- {
- // swap only works for strings
- if (JSON_HEDLEY_LIKELY(is_binary()))
- {
- using std::swap;
- swap(*(m_value.binary), other);
- }
- else
- {
- JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t::container_type&) with ", type_name()), this));
- }
- }
- /// @}
- //////////////////////////////////////////
- // lexicographical comparison operators //
- //////////////////////////////////////////
- /// @name lexicographical comparison operators
- /// @{
- // note parentheses around operands are necessary; see
- // https://github.com/nlohmann/json/issues/1530
- #define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result) \
- const auto lhs_type = lhs.type(); \
- const auto rhs_type = rhs.type(); \
- \
- if (lhs_type == rhs_type) /* NOLINT(readability/braces) */ \
- { \
- switch (lhs_type) \
- { \
- case value_t::array: \
- return (*lhs.m_value.array) op (*rhs.m_value.array); \
- \
- case value_t::object: \
- return (*lhs.m_value.object) op (*rhs.m_value.object); \
- \
- case value_t::null: \
- return (null_result); \
- \
- case value_t::string: \
- return (*lhs.m_value.string) op (*rhs.m_value.string); \
- \
- case value_t::boolean: \
- return (lhs.m_value.boolean) op (rhs.m_value.boolean); \
- \
- case value_t::number_integer: \
- return (lhs.m_value.number_integer) op (rhs.m_value.number_integer); \
- \
- case value_t::number_unsigned: \
- return (lhs.m_value.number_unsigned) op (rhs.m_value.number_unsigned); \
- \
- case value_t::number_float: \
- return (lhs.m_value.number_float) op (rhs.m_value.number_float); \
- \
- case value_t::binary: \
- return (*lhs.m_value.binary) op (*rhs.m_value.binary); \
- \
- case value_t::discarded: \
- default: \
- return (unordered_result); \
- } \
- } \
- else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) \
- { \
- return static_cast<number_float_t>(lhs.m_value.number_integer) op rhs.m_value.number_float; \
- } \
- else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) \
- { \
- return lhs.m_value.number_float op static_cast<number_float_t>(rhs.m_value.number_integer); \
- } \
- else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) \
- { \
- return static_cast<number_float_t>(lhs.m_value.number_unsigned) op rhs.m_value.number_float; \
- } \
- else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) \
- { \
- return lhs.m_value.number_float op static_cast<number_float_t>(rhs.m_value.number_unsigned); \
- } \
- else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) \
- { \
- return static_cast<number_integer_t>(lhs.m_value.number_unsigned) op rhs.m_value.number_integer; \
- } \
- else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) \
- { \
- return lhs.m_value.number_integer op static_cast<number_integer_t>(rhs.m_value.number_unsigned); \
- } \
- else if(compares_unordered(lhs, rhs))\
- {\
- return (unordered_result);\
- }\
- \
- return (default_result);
- JSON_PRIVATE_UNLESS_TESTED:
- // returns true if:
- // - any operand is NaN and the other operand is of number type
- // - any operand is discarded
- // in legacy mode, discarded values are considered ordered if
- // an operation is computed as an odd number of inverses of others
- static bool compares_unordered(const_reference lhs, const_reference rhs, bool inverse = false) noexcept
- {
- if ((lhs.is_number_float() && std::isnan(lhs.m_value.number_float) && rhs.is_number())
- || (rhs.is_number_float() && std::isnan(rhs.m_value.number_float) && lhs.is_number()))
- {
- return true;
- }
- #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
- return (lhs.is_discarded() || rhs.is_discarded()) && !inverse;
- #else
- static_cast<void>(inverse);
- return lhs.is_discarded() || rhs.is_discarded();
- #endif
- }
- private:
- bool compares_unordered(const_reference rhs, bool inverse = false) const noexcept
- {
- return compares_unordered(*this, rhs, inverse);
- }
- public:
- #if JSON_HAS_THREE_WAY_COMPARISON
- /// @brief comparison: equal
- /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
- bool operator==(const_reference rhs) const noexcept
- {
- #ifdef __GNUC__
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wfloat-equal"
- #endif
- const_reference lhs = *this;
- JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
- #ifdef __GNUC__
- #pragma GCC diagnostic pop
- #endif
- }
- /// @brief comparison: equal
- /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
- template<typename ScalarType>
- requires std::is_scalar_v<ScalarType>
- bool operator==(ScalarType rhs) const noexcept
- {
- return *this == basic_json(rhs);
- }
- /// @brief comparison: not equal
- /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
- bool operator!=(const_reference rhs) const noexcept
- {
- if (compares_unordered(rhs, true))
- {
- return false;
- }
- return !operator==(rhs);
- }
- /// @brief comparison: 3-way
- /// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/
- std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD*
- {
- const_reference lhs = *this;
- // default_result is used if we cannot compare values. In that case,
- // we compare types.
- JSON_IMPLEMENT_OPERATOR(<=>, // *NOPAD*
- std::partial_ordering::equivalent,
- std::partial_ordering::unordered,
- lhs_type <=> rhs_type) // *NOPAD*
- }
- /// @brief comparison: 3-way
- /// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/
- template<typename ScalarType>
- requires std::is_scalar_v<ScalarType>
- std::partial_ordering operator<=>(ScalarType rhs) const noexcept // *NOPAD*
- {
- return *this <=> basic_json(rhs); // *NOPAD*
- }
- #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
- // all operators that are computed as an odd number of inverses of others
- // need to be overloaded to emulate the legacy comparison behavior
- /// @brief comparison: less than or equal
- /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
- JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
- bool operator<=(const_reference rhs) const noexcept
- {
- if (compares_unordered(rhs, true))
- {
- return false;
- }
- return !(rhs < *this);
- }
- /// @brief comparison: less than or equal
- /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
- template<typename ScalarType>
- requires std::is_scalar_v<ScalarType>
- bool operator<=(ScalarType rhs) const noexcept
- {
- return *this <= basic_json(rhs);
- }
- /// @brief comparison: greater than or equal
- /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
- JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
- bool operator>=(const_reference rhs) const noexcept
- {
- if (compares_unordered(rhs, true))
- {
- return false;
- }
- return !(*this < rhs);
- }
- /// @brief comparison: greater than or equal
- /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
- template<typename ScalarType>
- requires std::is_scalar_v<ScalarType>
- bool operator>=(ScalarType rhs) const noexcept
- {
- return *this >= basic_json(rhs);
- }
- #endif
- #else
- /// @brief comparison: equal
- /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
- friend bool operator==(const_reference lhs, const_reference rhs) noexcept
- {
- #ifdef __GNUC__
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wfloat-equal"
- #endif
- JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
- #ifdef __GNUC__
- #pragma GCC diagnostic pop
- #endif
- }
- /// @brief comparison: equal
- /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
- template<typename ScalarType, typename std::enable_if<
- std::is_scalar<ScalarType>::value, int>::type = 0>
- friend bool operator==(const_reference lhs, ScalarType rhs) noexcept
- {
- return lhs == basic_json(rhs);
- }
- /// @brief comparison: equal
- /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
- template<typename ScalarType, typename std::enable_if<
- std::is_scalar<ScalarType>::value, int>::type = 0>
- friend bool operator==(ScalarType lhs, const_reference rhs) noexcept
- {
- return basic_json(lhs) == rhs;
- }
- /// @brief comparison: not equal
- /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
- friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
- {
- if (compares_unordered(lhs, rhs, true))
- {
- return false;
- }
- return !(lhs == rhs);
- }
- /// @brief comparison: not equal
- /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
- template<typename ScalarType, typename std::enable_if<
- std::is_scalar<ScalarType>::value, int>::type = 0>
- friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept
- {
- return lhs != basic_json(rhs);
- }
- /// @brief comparison: not equal
- /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
- template<typename ScalarType, typename std::enable_if<
- std::is_scalar<ScalarType>::value, int>::type = 0>
- friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept
- {
- return basic_json(lhs) != rhs;
- }
- /// @brief comparison: less than
- /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
- friend bool operator<(const_reference lhs, const_reference rhs) noexcept
- {
- // default_result is used if we cannot compare values. In that case,
- // we compare types. Note we have to call the operator explicitly,
- // because MSVC has problems otherwise.
- JSON_IMPLEMENT_OPERATOR( <, false, false, operator<(lhs_type, rhs_type))
- }
- /// @brief comparison: less than
- /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
- template<typename ScalarType, typename std::enable_if<
- std::is_scalar<ScalarType>::value, int>::type = 0>
- friend bool operator<(const_reference lhs, ScalarType rhs) noexcept
- {
- return lhs < basic_json(rhs);
- }
- /// @brief comparison: less than
- /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
- template<typename ScalarType, typename std::enable_if<
- std::is_scalar<ScalarType>::value, int>::type = 0>
- friend bool operator<(ScalarType lhs, const_reference rhs) noexcept
- {
- return basic_json(lhs) < rhs;
- }
- /// @brief comparison: less than or equal
- /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
- friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
- {
- if (compares_unordered(lhs, rhs, true))
- {
- return false;
- }
- return !(rhs < lhs);
- }
- /// @brief comparison: less than or equal
- /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
- template<typename ScalarType, typename std::enable_if<
- std::is_scalar<ScalarType>::value, int>::type = 0>
- friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept
- {
- return lhs <= basic_json(rhs);
- }
- /// @brief comparison: less than or equal
- /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
- template<typename ScalarType, typename std::enable_if<
- std::is_scalar<ScalarType>::value, int>::type = 0>
- friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept
- {
- return basic_json(lhs) <= rhs;
- }
- /// @brief comparison: greater than
- /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
- friend bool operator>(const_reference lhs, const_reference rhs) noexcept
- {
- // double inverse
- if (compares_unordered(lhs, rhs))
- {
- return false;
- }
- return !(lhs <= rhs);
- }
- /// @brief comparison: greater than
- /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
- template<typename ScalarType, typename std::enable_if<
- std::is_scalar<ScalarType>::value, int>::type = 0>
- friend bool operator>(const_reference lhs, ScalarType rhs) noexcept
- {
- return lhs > basic_json(rhs);
- }
- /// @brief comparison: greater than
- /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
- template<typename ScalarType, typename std::enable_if<
- std::is_scalar<ScalarType>::value, int>::type = 0>
- friend bool operator>(ScalarType lhs, const_reference rhs) noexcept
- {
- return basic_json(lhs) > rhs;
- }
- /// @brief comparison: greater than or equal
- /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
- friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
- {
- if (compares_unordered(lhs, rhs, true))
- {
- return false;
- }
- return !(lhs < rhs);
- }
- /// @brief comparison: greater than or equal
- /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
- template<typename ScalarType, typename std::enable_if<
- std::is_scalar<ScalarType>::value, int>::type = 0>
- friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept
- {
- return lhs >= basic_json(rhs);
- }
- /// @brief comparison: greater than or equal
- /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
- template<typename ScalarType, typename std::enable_if<
- std::is_scalar<ScalarType>::value, int>::type = 0>
- friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept
- {
- return basic_json(lhs) >= rhs;
- }
- #endif
- #undef JSON_IMPLEMENT_OPERATOR
- /// @}
- ///////////////////
- // serialization //
- ///////////////////
- /// @name serialization
- /// @{
- #ifndef JSON_NO_IO
- /// @brief serialize to stream
- /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
- friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
- {
- // read width member and use it as indentation parameter if nonzero
- const bool pretty_print = o.width() > 0;
- const auto indentation = pretty_print ? o.width() : 0;
- // reset width to 0 for subsequent calls to this stream
- o.width(0);
- // do the actual serialization
- serializer s(detail::output_adapter<char>(o), o.fill());
- s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
- return o;
- }
- /// @brief serialize to stream
- /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
- /// @deprecated This function is deprecated since 3.0.0 and will be removed in
- /// version 4.0.0 of the library. Please use
- /// operator<<(std::ostream&, const basic_json&) instead; that is,
- /// replace calls like `j >> o;` with `o << j;`.
- JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&))
- friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
- {
- return o << j;
- }
- #endif // JSON_NO_IO
- /// @}
- /////////////////////
- // deserialization //
- /////////////////////
- /// @name deserialization
- /// @{
- /// @brief deserialize from a compatible input
- /// @sa https://json.nlohmann.me/api/basic_json/parse/
- template<typename InputType>
- JSON_HEDLEY_WARN_UNUSED_RESULT
- static basic_json parse(InputType&& i,
- const parser_callback_t cb = nullptr,
- const bool allow_exceptions = true,
- const bool ignore_comments = false)
- {
- basic_json result;
- parser(detail::input_adapter(std::forward<InputType>(i)), cb, allow_exceptions, ignore_comments).parse(true, result);
- return result;
- }
- /// @brief deserialize from a pair of character iterators
- /// @sa https://json.nlohmann.me/api/basic_json/parse/
- template<typename IteratorType>
- JSON_HEDLEY_WARN_UNUSED_RESULT
- static basic_json parse(IteratorType first,
- IteratorType last,
- const parser_callback_t cb = nullptr,
- const bool allow_exceptions = true,
- const bool ignore_comments = false)
- {
- basic_json result;
- parser(detail::input_adapter(std::move(first), std::move(last)), cb, allow_exceptions, ignore_comments).parse(true, result);
- return result;
- }
- JSON_HEDLEY_WARN_UNUSED_RESULT
- JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
- static basic_json parse(detail::span_input_adapter&& i,
- const parser_callback_t cb = nullptr,
- const bool allow_exceptions = true,
- const bool ignore_comments = false)
- {
- basic_json result;
- parser(i.get(), cb, allow_exceptions, ignore_comments).parse(true, result);
- return result;
- }
- /// @brief check if the input is valid JSON
- /// @sa https://json.nlohmann.me/api/basic_json/accept/
- template<typename InputType>
- static bool accept(InputType&& i,
- const bool ignore_comments = false)
- {
- return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments).accept(true);
- }
- /// @brief check if the input is valid JSON
- /// @sa https://json.nlohmann.me/api/basic_json/accept/
- template<typename IteratorType>
- static bool accept(IteratorType first, IteratorType last,
- const bool ignore_comments = false)
- {
- return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments).accept(true);
- }
- JSON_HEDLEY_WARN_UNUSED_RESULT
- JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
- static bool accept(detail::span_input_adapter&& i,
- const bool ignore_comments = false)
- {
- return parser(i.get(), nullptr, false, ignore_comments).accept(true);
- }
- /// @brief generate SAX events
- /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
- template <typename InputType, typename SAX>
- JSON_HEDLEY_NON_NULL(2)
- static bool sax_parse(InputType&& i, SAX* sax,
- input_format_t format = input_format_t::json,
- const bool strict = true,
- const bool ignore_comments = false)
- {
- auto ia = detail::input_adapter(std::forward<InputType>(i));
- return format == input_format_t::json
- ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
- : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
- }
- /// @brief generate SAX events
- /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
- template<class IteratorType, class SAX>
- JSON_HEDLEY_NON_NULL(3)
- static bool sax_parse(IteratorType first, IteratorType last, SAX* sax,
- input_format_t format = input_format_t::json,
- const bool strict = true,
- const bool ignore_comments = false)
- {
- auto ia = detail::input_adapter(std::move(first), std::move(last));
- return format == input_format_t::json
- ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
- : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
- }
- /// @brief generate SAX events
- /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
- /// @deprecated This function is deprecated since 3.8.0 and will be removed in
- /// version 4.0.0 of the library. Please use
- /// sax_parse(ptr, ptr + len) instead.
- template <typename SAX>
- JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
- JSON_HEDLEY_NON_NULL(2)
- static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
- input_format_t format = input_format_t::json,
- const bool strict = true,
- const bool ignore_comments = false)
- {
- auto ia = i.get();
- return format == input_format_t::json
- // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
- ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
- // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
- : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
- }
- #ifndef JSON_NO_IO
- /// @brief deserialize from stream
- /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
- /// @deprecated This stream operator is deprecated since 3.0.0 and will be removed in
- /// version 4.0.0 of the library. Please use
- /// operator>>(std::istream&, basic_json&) instead; that is,
- /// replace calls like `j << i;` with `i >> j;`.
- JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&))
- friend std::istream& operator<<(basic_json& j, std::istream& i)
- {
- return operator>>(i, j);
- }
- /// @brief deserialize from stream
- /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
- friend std::istream& operator>>(std::istream& i, basic_json& j)
- {
- parser(detail::input_adapter(i)).parse(false, j);
- return i;
- }
- #endif // JSON_NO_IO
- /// @}
- ///////////////////////////
- // convenience functions //
- ///////////////////////////
- /// @brief return the type as string
- /// @sa https://json.nlohmann.me/api/basic_json/type_name/
- JSON_HEDLEY_RETURNS_NON_NULL
- const char* type_name() const noexcept
- {
- switch (m_type)
- {
- case value_t::null:
- return "null";
- case value_t::object:
- return "object";
- case value_t::array:
- return "array";
- case value_t::string:
- return "string";
- case value_t::boolean:
- return "boolean";
- case value_t::binary:
- return "binary";
- case value_t::discarded:
- return "discarded";
- case value_t::number_integer:
- case value_t::number_unsigned:
- case value_t::number_float:
- default:
- return "number";
- }
- }
- JSON_PRIVATE_UNLESS_TESTED:
- //////////////////////
- // member variables //
- //////////////////////
- /// the type of the current element
- value_t m_type = value_t::null;
- /// the value of the current element
- json_value m_value = {};
- #if JSON_DIAGNOSTICS
- /// a pointer to a parent value (for debugging purposes)
- basic_json* m_parent = nullptr;
- #endif
- //////////////////////////////////////////
- // binary serialization/deserialization //
- //////////////////////////////////////////
- /// @name binary serialization/deserialization support
- /// @{
- public:
- /// @brief create a CBOR serialization of a given JSON value
- /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
- static std::vector<std::uint8_t> to_cbor(const basic_json& j)
- {
- std::vector<std::uint8_t> result;
- to_cbor(j, result);
- return result;
- }
- /// @brief create a CBOR serialization of a given JSON value
- /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
- static void to_cbor(const basic_json& j, detail::output_adapter<std::uint8_t> o)
- {
- binary_writer<std::uint8_t>(o).write_cbor(j);
- }
- /// @brief create a CBOR serialization of a given JSON value
- /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
- static void to_cbor(const basic_json& j, detail::output_adapter<char> o)
- {
- binary_writer<char>(o).write_cbor(j);
- }
- /// @brief create a MessagePack serialization of a given JSON value
- /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
- static std::vector<std::uint8_t> to_msgpack(const basic_json& j)
- {
- std::vector<std::uint8_t> result;
- to_msgpack(j, result);
- return result;
- }
- /// @brief create a MessagePack serialization of a given JSON value
- /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
- static void to_msgpack(const basic_json& j, detail::output_adapter<std::uint8_t> o)
- {
- binary_writer<std::uint8_t>(o).write_msgpack(j);
- }
- /// @brief create a MessagePack serialization of a given JSON value
- /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
- static void to_msgpack(const basic_json& j, detail::output_adapter<char> o)
- {
- binary_writer<char>(o).write_msgpack(j);
- }
- /// @brief create a UBJSON serialization of a given JSON value
- /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
- static std::vector<std::uint8_t> to_ubjson(const basic_json& j,
- const bool use_size = false,
- const bool use_type = false)
- {
- std::vector<std::uint8_t> result;
- to_ubjson(j, result, use_size, use_type);
- return result;
- }
- /// @brief create a UBJSON serialization of a given JSON value
- /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
- static void to_ubjson(const basic_json& j, detail::output_adapter<std::uint8_t> o,
- const bool use_size = false, const bool use_type = false)
- {
- binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type);
- }
- /// @brief create a UBJSON serialization of a given JSON value
- /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
- static void to_ubjson(const basic_json& j, detail::output_adapter<char> o,
- const bool use_size = false, const bool use_type = false)
- {
- binary_writer<char>(o).write_ubjson(j, use_size, use_type);
- }
- /// @brief create a BJData serialization of a given JSON value
- /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
- static std::vector<std::uint8_t> to_bjdata(const basic_json& j,
- const bool use_size = false,
- const bool use_type = false)
- {
- std::vector<std::uint8_t> result;
- to_bjdata(j, result, use_size, use_type);
- return result;
- }
- /// @brief create a BJData serialization of a given JSON value
- /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
- static void to_bjdata(const basic_json& j, detail::output_adapter<std::uint8_t> o,
- const bool use_size = false, const bool use_type = false)
- {
- binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type, true, true);
- }
- /// @brief create a BJData serialization of a given JSON value
- /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
- static void to_bjdata(const basic_json& j, detail::output_adapter<char> o,
- const bool use_size = false, const bool use_type = false)
- {
- binary_writer<char>(o).write_ubjson(j, use_size, use_type, true, true);
- }
- /// @brief create a BSON serialization of a given JSON value
- /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
- static std::vector<std::uint8_t> to_bson(const basic_json& j)
- {
- std::vector<std::uint8_t> result;
- to_bson(j, result);
- return result;
- }
- /// @brief create a BSON serialization of a given JSON value
- /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
- static void to_bson(const basic_json& j, detail::output_adapter<std::uint8_t> o)
- {
- binary_writer<std::uint8_t>(o).write_bson(j);
- }
- /// @brief create a BSON serialization of a given JSON value
- /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
- static void to_bson(const basic_json& j, detail::output_adapter<char> o)
- {
- binary_writer<char>(o).write_bson(j);
- }
- /// @brief create a JSON value from an input in CBOR format
- /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/
- template<typename InputType>
- JSON_HEDLEY_WARN_UNUSED_RESULT
- static basic_json from_cbor(InputType&& i,
- const bool strict = true,
- const bool allow_exceptions = true,
- const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
- {
- basic_json result;
- detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
- auto ia = detail::input_adapter(std::forward<InputType>(i));
- const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
- return res ? result : basic_json(value_t::discarded);
- }
- /// @brief create a JSON value from an input in CBOR format
- /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/
- template<typename IteratorType>
- JSON_HEDLEY_WARN_UNUSED_RESULT
- static basic_json from_cbor(IteratorType first, IteratorType last,
- const bool strict = true,
- const bool allow_exceptions = true,
- const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
- {
- basic_json result;
- detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
- auto ia = detail::input_adapter(std::move(first), std::move(last));
- const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
- return res ? result : basic_json(value_t::discarded);
- }
- template<typename T>
- JSON_HEDLEY_WARN_UNUSED_RESULT
- JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
- static basic_json from_cbor(const T* ptr, std::size_t len,
- const bool strict = true,
- const bool allow_exceptions = true,
- const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
- {
- return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
- }
- JSON_HEDLEY_WARN_UNUSED_RESULT
- JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
- static basic_json from_cbor(detail::span_input_adapter&& i,
- const bool strict = true,
- const bool allow_exceptions = true,
- const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
- {
- basic_json result;
- detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
- auto ia = i.get();
- // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
- const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
- return res ? result : basic_json(value_t::discarded);
- }
- /// @brief create a JSON value from an input in MessagePack format
- /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/
- template<typename InputType>
- JSON_HEDLEY_WARN_UNUSED_RESULT
- static basic_json from_msgpack(InputType&& i,
- const bool strict = true,
- const bool allow_exceptions = true)
- {
- basic_json result;
- detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
- auto ia = detail::input_adapter(std::forward<InputType>(i));
- const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
- return res ? result : basic_json(value_t::discarded);
- }
- /// @brief create a JSON value from an input in MessagePack format
- /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/
- template<typename IteratorType>
- JSON_HEDLEY_WARN_UNUSED_RESULT
- static basic_json from_msgpack(IteratorType first, IteratorType last,
- const bool strict = true,
- const bool allow_exceptions = true)
- {
- basic_json result;
- detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
- auto ia = detail::input_adapter(std::move(first), std::move(last));
- const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
- return res ? result : basic_json(value_t::discarded);
- }
- template<typename T>
- JSON_HEDLEY_WARN_UNUSED_RESULT
- JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
- static basic_json from_msgpack(const T* ptr, std::size_t len,
- const bool strict = true,
- const bool allow_exceptions = true)
- {
- return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
- }
- JSON_HEDLEY_WARN_UNUSED_RESULT
- JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
- static basic_json from_msgpack(detail::span_input_adapter&& i,
- const bool strict = true,
- const bool allow_exceptions = true)
- {
- basic_json result;
- detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
- auto ia = i.get();
- // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
- const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
- return res ? result : basic_json(value_t::discarded);
- }
- /// @brief create a JSON value from an input in UBJSON format
- /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/
- template<typename InputType>
- JSON_HEDLEY_WARN_UNUSED_RESULT
- static basic_json from_ubjson(InputType&& i,
- const bool strict = true,
- const bool allow_exceptions = true)
- {
- basic_json result;
- detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
- auto ia = detail::input_adapter(std::forward<InputType>(i));
- const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
- return res ? result : basic_json(value_t::discarded);
- }
- /// @brief create a JSON value from an input in UBJSON format
- /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/
- template<typename IteratorType>
- JSON_HEDLEY_WARN_UNUSED_RESULT
- static basic_json from_ubjson(IteratorType first, IteratorType last,
- const bool strict = true,
- const bool allow_exceptions = true)
- {
- basic_json result;
- detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
- auto ia = detail::input_adapter(std::move(first), std::move(last));
- const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
- return res ? result : basic_json(value_t::discarded);
- }
- template<typename T>
- JSON_HEDLEY_WARN_UNUSED_RESULT
- JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
- static basic_json from_ubjson(const T* ptr, std::size_t len,
- const bool strict = true,
- const bool allow_exceptions = true)
- {
- return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
- }
- JSON_HEDLEY_WARN_UNUSED_RESULT
- JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
- static basic_json from_ubjson(detail::span_input_adapter&& i,
- const bool strict = true,
- const bool allow_exceptions = true)
- {
- basic_json result;
- detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
- auto ia = i.get();
- // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
- const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
- return res ? result : basic_json(value_t::discarded);
- }
- /// @brief create a JSON value from an input in BJData format
- /// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/
- template<typename InputType>
- JSON_HEDLEY_WARN_UNUSED_RESULT
- static basic_json from_bjdata(InputType&& i,
- const bool strict = true,
- const bool allow_exceptions = true)
- {
- basic_json result;
- detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
- auto ia = detail::input_adapter(std::forward<InputType>(i));
- const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict);
- return res ? result : basic_json(value_t::discarded);
- }
- /// @brief create a JSON value from an input in BJData format
- /// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/
- template<typename IteratorType>
- JSON_HEDLEY_WARN_UNUSED_RESULT
- static basic_json from_bjdata(IteratorType first, IteratorType last,
- const bool strict = true,
- const bool allow_exceptions = true)
- {
- basic_json result;
- detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
- auto ia = detail::input_adapter(std::move(first), std::move(last));
- const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict);
- return res ? result : basic_json(value_t::discarded);
- }
- /// @brief create a JSON value from an input in BSON format
- /// @sa https://json.nlohmann.me/api/basic_json/from_bson/
- template<typename InputType>
- JSON_HEDLEY_WARN_UNUSED_RESULT
- static basic_json from_bson(InputType&& i,
- const bool strict = true,
- const bool allow_exceptions = true)
- {
- basic_json result;
- detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
- auto ia = detail::input_adapter(std::forward<InputType>(i));
- const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
- return res ? result : basic_json(value_t::discarded);
- }
- /// @brief create a JSON value from an input in BSON format
- /// @sa https://json.nlohmann.me/api/basic_json/from_bson/
- template<typename IteratorType>
- JSON_HEDLEY_WARN_UNUSED_RESULT
- static basic_json from_bson(IteratorType first, IteratorType last,
- const bool strict = true,
- const bool allow_exceptions = true)
- {
- basic_json result;
- detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
- auto ia = detail::input_adapter(std::move(first), std::move(last));
- const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
- return res ? result : basic_json(value_t::discarded);
- }
- template<typename T>
- JSON_HEDLEY_WARN_UNUSED_RESULT
- JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
- static basic_json from_bson(const T* ptr, std::size_t len,
- const bool strict = true,
- const bool allow_exceptions = true)
- {
- return from_bson(ptr, ptr + len, strict, allow_exceptions);
- }
- JSON_HEDLEY_WARN_UNUSED_RESULT
- JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
- static basic_json from_bson(detail::span_input_adapter&& i,
- const bool strict = true,
- const bool allow_exceptions = true)
- {
- basic_json result;
- detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
- auto ia = i.get();
- // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
- const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
- return res ? result : basic_json(value_t::discarded);
- }
- /// @}
- //////////////////////////
- // JSON Pointer support //
- //////////////////////////
- /// @name JSON Pointer functions
- /// @{
- /// @brief access specified element via JSON Pointer
- /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
- reference operator[](const json_pointer& ptr)
- {
- return ptr.get_unchecked(this);
- }
- template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
- JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
- reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr)
- {
- return ptr.get_unchecked(this);
- }
- /// @brief access specified element via JSON Pointer
- /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
- const_reference operator[](const json_pointer& ptr) const
- {
- return ptr.get_unchecked(this);
- }
- template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
- JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
- const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
- {
- return ptr.get_unchecked(this);
- }
- /// @brief access specified element via JSON Pointer
- /// @sa https://json.nlohmann.me/api/basic_json/at/
- reference at(const json_pointer& ptr)
- {
- return ptr.get_checked(this);
- }
- template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
- JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
- reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr)
- {
- return ptr.get_checked(this);
- }
- /// @brief access specified element via JSON Pointer
- /// @sa https://json.nlohmann.me/api/basic_json/at/
- const_reference at(const json_pointer& ptr) const
- {
- return ptr.get_checked(this);
- }
- template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
- JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
- const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
- {
- return ptr.get_checked(this);
- }
- /// @brief return flattened JSON value
- /// @sa https://json.nlohmann.me/api/basic_json/flatten/
- basic_json flatten() const
- {
- basic_json result(value_t::object);
- json_pointer::flatten("", *this, result);
- return result;
- }
- /// @brief unflatten a previously flattened JSON value
- /// @sa https://json.nlohmann.me/api/basic_json/unflatten/
- basic_json unflatten() const
- {
- return json_pointer::unflatten(*this);
- }
- /// @}
- //////////////////////////
- // JSON Patch functions //
- //////////////////////////
- /// @name JSON Patch functions
- /// @{
- /// @brief applies a JSON patch in-place without copying the object
- /// @sa https://json.nlohmann.me/api/basic_json/patch/
- void patch_inplace(const basic_json& json_patch)
- {
- basic_json& result = *this;
- // the valid JSON Patch operations
- enum class patch_operations {add, remove, replace, move, copy, test, invalid};
- const auto get_op = [](const std::string & op)
- {
- if (op == "add")
- {
- return patch_operations::add;
- }
- if (op == "remove")
- {
- return patch_operations::remove;
- }
- if (op == "replace")
- {
- return patch_operations::replace;
- }
- if (op == "move")
- {
- return patch_operations::move;
- }
- if (op == "copy")
- {
- return patch_operations::copy;
- }
- if (op == "test")
- {
- return patch_operations::test;
- }
- return patch_operations::invalid;
- };
- // wrapper for "add" operation; add value at ptr
- const auto operation_add = [&result](json_pointer & ptr, basic_json val)
- {
- // adding to the root of the target document means replacing it
- if (ptr.empty())
- {
- result = val;
- return;
- }
- // make sure the top element of the pointer exists
- json_pointer const top_pointer = ptr.top();
- if (top_pointer != ptr)
- {
- result.at(top_pointer);
- }
- // get reference to parent of JSON pointer ptr
- const auto last_path = ptr.back();
- ptr.pop_back();
- // parent must exist when performing patch add per RFC6902 specs
- basic_json& parent = result.at(ptr);
- switch (parent.m_type)
- {
- case value_t::null:
- case value_t::object:
- {
- // use operator[] to add value
- parent[last_path] = val;
- break;
- }
- case value_t::array:
- {
- if (last_path == "-")
- {
- // special case: append to back
- parent.push_back(val);
- }
- else
- {
- const auto idx = json_pointer::template array_index<basic_json_t>(last_path);
- if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
- {
- // avoid undefined behavior
- JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), &parent));
- }
- // default case: insert add offset
- parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
- }
- break;
- }
- // if there exists a parent it cannot be primitive
- case value_t::string: // LCOV_EXCL_LINE
- case value_t::boolean: // LCOV_EXCL_LINE
- case value_t::number_integer: // LCOV_EXCL_LINE
- case value_t::number_unsigned: // LCOV_EXCL_LINE
- case value_t::number_float: // LCOV_EXCL_LINE
- case value_t::binary: // LCOV_EXCL_LINE
- case value_t::discarded: // LCOV_EXCL_LINE
- default: // LCOV_EXCL_LINE
- JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
- }
- };
- // wrapper for "remove" operation; remove value at ptr
- const auto operation_remove = [this, &result](json_pointer & ptr)
- {
- // get reference to parent of JSON pointer ptr
- const auto last_path = ptr.back();
- ptr.pop_back();
- basic_json& parent = result.at(ptr);
- // remove child
- if (parent.is_object())
- {
- // perform range check
- auto it = parent.find(last_path);
- if (JSON_HEDLEY_LIKELY(it != parent.end()))
- {
- parent.erase(it);
- }
- else
- {
- JSON_THROW(out_of_range::create(403, detail::concat("key '", last_path, "' not found"), this));
- }
- }
- else if (parent.is_array())
- {
- // note erase performs range check
- parent.erase(json_pointer::template array_index<basic_json_t>(last_path));
- }
- };
- // type check: top level value must be an array
- if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array()))
- {
- JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &json_patch));
- }
- // iterate and apply the operations
- for (const auto& val : json_patch)
- {
- // wrapper to get a value for an operation
- const auto get_value = [&val](const std::string & op,
- const std::string & member,
- bool string_type) -> basic_json &
- {
- // find value
- auto it = val.m_value.object->find(member);
- // context-sensitive error message
- const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\'');
- // check if desired value is present
- if (JSON_HEDLEY_UNLIKELY(it == val.m_value.object->end()))
- {
- // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
- JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have member '", member, "'"), &val));
- }
- // check if result is of type string
- if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
- {
- // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
- JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have string member '", member, "'"), &val));
- }
- // no error: return value
- return it->second;
- };
- // type check: every element of the array must be an object
- if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
- {
- JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &val));
- }
- // collect mandatory members
- const auto op = get_value("op", "op", true).template get<std::string>();
- const auto path = get_value(op, "path", true).template get<std::string>();
- json_pointer ptr(path);
- switch (get_op(op))
- {
- case patch_operations::add:
- {
- operation_add(ptr, get_value("add", "value", false));
- break;
- }
- case patch_operations::remove:
- {
- operation_remove(ptr);
- break;
- }
- case patch_operations::replace:
- {
- // the "path" location must exist - use at()
- result.at(ptr) = get_value("replace", "value", false);
- break;
- }
- case patch_operations::move:
- {
- const auto from_path = get_value("move", "from", true).template get<std::string>();
- json_pointer from_ptr(from_path);
- // the "from" location must exist - use at()
- basic_json const v = result.at(from_ptr);
- // The move operation is functionally identical to a
- // "remove" operation on the "from" location, followed
- // immediately by an "add" operation at the target
- // location with the value that was just removed.
- operation_remove(from_ptr);
- operation_add(ptr, v);
- break;
- }
- case patch_operations::copy:
- {
- const auto from_path = get_value("copy", "from", true).template get<std::string>();
- const json_pointer from_ptr(from_path);
- // the "from" location must exist - use at()
- basic_json const v = result.at(from_ptr);
- // The copy is functionally identical to an "add"
- // operation at the target location using the value
- // specified in the "from" member.
- operation_add(ptr, v);
- break;
- }
- case patch_operations::test:
- {
- bool success = false;
- JSON_TRY
- {
- // check if "value" matches the one at "path"
- // the "path" location must exist - use at()
- success = (result.at(ptr) == get_value("test", "value", false));
- }
- JSON_INTERNAL_CATCH (out_of_range&)
- {
- // ignore out of range errors: success remains false
- }
- // throw an exception if test fails
- if (JSON_HEDLEY_UNLIKELY(!success))
- {
- JSON_THROW(other_error::create(501, detail::concat("unsuccessful: ", val.dump()), &val));
- }
- break;
- }
- case patch_operations::invalid:
- default:
- {
- // op must be "add", "remove", "replace", "move", "copy", or
- // "test"
- JSON_THROW(parse_error::create(105, 0, detail::concat("operation value '", op, "' is invalid"), &val));
- }
- }
- }
- }
- /// @brief applies a JSON patch to a copy of the current object
- /// @sa https://json.nlohmann.me/api/basic_json/patch/
- basic_json patch(const basic_json& json_patch) const
- {
- basic_json result = *this;
- result.patch_inplace(json_patch);
- return result;
- }
- /// @brief creates a diff as a JSON patch
- /// @sa https://json.nlohmann.me/api/basic_json/diff/
- JSON_HEDLEY_WARN_UNUSED_RESULT
- static basic_json diff(const basic_json& source, const basic_json& target,
- const std::string& path = "")
- {
- // the patch
- basic_json result(value_t::array);
- // if the values are the same, return empty patch
- if (source == target)
- {
- return result;
- }
- if (source.type() != target.type())
- {
- // different types: replace value
- result.push_back(
- {
- {"op", "replace"}, {"path", path}, {"value", target}
- });
- return result;
- }
- switch (source.type())
- {
- case value_t::array:
- {
- // first pass: traverse common elements
- std::size_t i = 0;
- while (i < source.size() && i < target.size())
- {
- // recursive call to compare array values at index i
- auto temp_diff = diff(source[i], target[i], detail::concat(path, '/', std::to_string(i)));
- result.insert(result.end(), temp_diff.begin(), temp_diff.end());
- ++i;
- }
- // We now reached the end of at least one array
- // in a second pass, traverse the remaining elements
- // remove my remaining elements
- const auto end_index = static_cast<difference_type>(result.size());
- while (i < source.size())
- {
- // add operations in reverse order to avoid invalid
- // indices
- result.insert(result.begin() + end_index, object(
- {
- {"op", "remove"},
- {"path", detail::concat(path, '/', std::to_string(i))}
- }));
- ++i;
- }
- // add other remaining elements
- while (i < target.size())
- {
- result.push_back(
- {
- {"op", "add"},
- {"path", detail::concat(path, "/-")},
- {"value", target[i]}
- });
- ++i;
- }
- break;
- }
- case value_t::object:
- {
- // first pass: traverse this object's elements
- for (auto it = source.cbegin(); it != source.cend(); ++it)
- {
- // escape the key name to be used in a JSON patch
- const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
- if (target.find(it.key()) != target.end())
- {
- // recursive call to compare object values at key it
- auto temp_diff = diff(it.value(), target[it.key()], path_key);
- result.insert(result.end(), temp_diff.begin(), temp_diff.end());
- }
- else
- {
- // found a key that is not in o -> remove it
- result.push_back(object(
- {
- {"op", "remove"}, {"path", path_key}
- }));
- }
- }
- // second pass: traverse other object's elements
- for (auto it = target.cbegin(); it != target.cend(); ++it)
- {
- if (source.find(it.key()) == source.end())
- {
- // found a key that is not in this -> add it
- const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
- result.push_back(
- {
- {"op", "add"}, {"path", path_key},
- {"value", it.value()}
- });
- }
- }
- break;
- }
- case value_t::null:
- case value_t::string:
- case value_t::boolean:
- case value_t::number_integer:
- case value_t::number_unsigned:
- case value_t::number_float:
- case value_t::binary:
- case value_t::discarded:
- default:
- {
- // both primitive type: replace value
- result.push_back(
- {
- {"op", "replace"}, {"path", path}, {"value", target}
- });
- break;
- }
- }
- return result;
- }
- /// @}
- ////////////////////////////////
- // JSON Merge Patch functions //
- ////////////////////////////////
- /// @name JSON Merge Patch functions
- /// @{
- /// @brief applies a JSON Merge Patch
- /// @sa https://json.nlohmann.me/api/basic_json/merge_patch/
- void merge_patch(const basic_json& apply_patch)
- {
- if (apply_patch.is_object())
- {
- if (!is_object())
- {
- *this = object();
- }
- for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)
- {
- if (it.value().is_null())
- {
- erase(it.key());
- }
- else
- {
- operator[](it.key()).merge_patch(it.value());
- }
- }
- }
- else
- {
- *this = apply_patch;
- }
- }
- /// @}
- };
- /// @brief user-defined to_string function for JSON values
- /// @sa https://json.nlohmann.me/api/basic_json/to_string/
- NLOHMANN_BASIC_JSON_TPL_DECLARATION
- std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j)
- {
- return j.dump();
- }
- inline namespace literals
- {
- inline namespace json_literals
- {
- /// @brief user-defined string literal for JSON values
- /// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json/
- JSON_HEDLEY_NON_NULL(1)
- inline nlohmann::json operator "" _json(const char* s, std::size_t n)
- {
- return nlohmann::json::parse(s, s + n);
- }
- /// @brief user-defined string literal for JSON pointer
- /// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json_pointer/
- JSON_HEDLEY_NON_NULL(1)
- inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
- {
- return nlohmann::json::json_pointer(std::string(s, n));
- }
- } // namespace json_literals
- } // namespace literals
- NLOHMANN_JSON_NAMESPACE_END
- ///////////////////////
- // nonmember support //
- ///////////////////////
- namespace std // NOLINT(cert-dcl58-cpp)
- {
- /// @brief hash value for JSON objects
- /// @sa https://json.nlohmann.me/api/basic_json/std_hash/
- NLOHMANN_BASIC_JSON_TPL_DECLARATION
- struct hash<nlohmann::NLOHMANN_BASIC_JSON_TPL> // NOLINT(cert-dcl58-cpp)
- {
- std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const
- {
- return nlohmann::detail::hash(j);
- }
- };
- // specialization for std::less<value_t>
- template<>
- struct less< ::nlohmann::detail::value_t> // do not remove the space after '<', see https://github.com/nlohmann/json/pull/679
- {
- /*!
- @brief compare two value_t enum values
- @since version 3.0.0
- */
- bool operator()(::nlohmann::detail::value_t lhs,
- ::nlohmann::detail::value_t rhs) const noexcept
- {
- #if JSON_HAS_THREE_WAY_COMPARISON
- return std::is_lt(lhs <=> rhs); // *NOPAD*
- #else
- return ::nlohmann::detail::operator<(lhs, rhs);
- #endif
- }
- };
- // C++20 prohibit function specialization in the std namespace.
- #ifndef JSON_HAS_CPP_20
- /// @brief exchanges the values of two JSON objects
- /// @sa https://json.nlohmann.me/api/basic_json/std_swap/
- NLOHMANN_BASIC_JSON_TPL_DECLARATION
- inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept( // NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp)
- is_nothrow_move_constructible<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value&& // NOLINT(misc-redundant-expression)
- is_nothrow_move_assignable<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value)
- {
- j1.swap(j2);
- }
- #endif
- } // namespace std
- #if JSON_USE_GLOBAL_UDLS
- using nlohmann::literals::json_literals::operator "" _json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
- using nlohmann::literals::json_literals::operator "" _json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
- #endif
- #include <nlohmann/detail/macro_unscope.hpp>
- #endif // INCLUDE_NLOHMANN_JSON_HPP_
|