2020-06-20 15:11:37 +03:00
/*
__ _____ _____ _____
__ | | __ | | | | JSON for Modern C + + ( test suite )
| | | __ | | | | | | version 3.8 .0
| _____ | _____ | _____ | _ | ___ | https : //github.com/nlohmann/json
Licensed under the MIT License < http : //opensource.org/licenses/MIT>.
SPDX - License - Identifier : MIT
Copyright ( c ) 2013 - 2019 Niels Lohmann < http : //nlohmann.me>.
Permission is hereby granted , free of charge , to any person obtaining a copy
of this software and associated documentation files ( the " Software " ) , to deal
in the Software without restriction , including without limitation the rights
to use , copy , modify , merge , publish , distribute , sublicense , and / or sell
copies of the Software , and to permit persons to whom the Software is
furnished to do so , subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software .
THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM ,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE .
*/
2020-07-19 20:12:13 +03:00
# include <string>
# include <vector>
2020-07-19 20:22:16 +03:00
# include <cassert>
2020-06-20 15:11:37 +03:00
# include "doctest_compatibility.h"
# include <nlohmann/json.hpp>
using nlohmann : : json ;
namespace persons
{
class person_with_private_data
{
private :
2020-07-06 13:37:39 +03:00
std : : string name = " " ;
2020-06-20 15:11:37 +03:00
int age = 0 ;
2020-07-06 13:37:39 +03:00
json metadata = nullptr ;
2020-06-20 15:11:37 +03:00
public :
bool operator = = ( const person_with_private_data & rhs ) const
{
2020-06-30 20:55:40 +03:00
return name = = rhs . name & & age = = rhs . age & & metadata = = rhs . metadata ;
2020-06-20 15:11:37 +03:00
}
person_with_private_data ( ) = default ;
2020-07-06 13:37:39 +03:00
person_with_private_data ( std : : string name_ , int age_ , json metadata_ )
: name ( std : : move ( name_ ) )
, age ( age_ )
, metadata ( std : : move ( metadata_ ) )
2020-06-20 15:11:37 +03:00
{ }
2020-07-06 13:37:39 +03:00
NLOHMANN_DEFINE_TYPE_INTRUSIVE ( person_with_private_data , age , name , metadata )
2020-06-20 15:11:37 +03:00
} ;
class person_without_private_data_1
{
public :
2020-07-08 15:02:28 +03:00
std : : string name = " " ;
int age = 0 ;
json metadata = nullptr ;
2020-06-20 15:11:37 +03:00
bool operator = = ( const person_without_private_data_1 & rhs ) const
{
2020-06-30 20:55:40 +03:00
return name = = rhs . name & & age = = rhs . age & & metadata = = rhs . metadata ;
2020-06-20 15:11:37 +03:00
}
person_without_private_data_1 ( ) = default ;
2020-07-06 13:37:39 +03:00
person_without_private_data_1 ( std : : string name_ , int age_ , json metadata_ )
: name ( std : : move ( name_ ) )
, age ( age_ )
, metadata ( std : : move ( metadata_ ) )
2020-06-20 15:11:37 +03:00
{ }
2020-07-06 13:37:39 +03:00
NLOHMANN_DEFINE_TYPE_INTRUSIVE ( person_without_private_data_1 , age , name , metadata )
2020-06-20 15:11:37 +03:00
} ;
class person_without_private_data_2
{
public :
2020-07-08 15:02:28 +03:00
std : : string name = " " ;
int age = 0 ;
json metadata = nullptr ;
2020-06-20 15:11:37 +03:00
bool operator = = ( const person_without_private_data_2 & rhs ) const
{
2020-06-30 20:55:40 +03:00
return name = = rhs . name & & age = = rhs . age & & metadata = = rhs . metadata ;
2020-06-20 15:11:37 +03:00
}
person_without_private_data_2 ( ) = default ;
2020-07-06 13:37:39 +03:00
person_without_private_data_2 ( std : : string name_ , int age_ , json metadata_ )
: name ( std : : move ( name_ ) )
, age ( age_ )
, metadata ( std : : move ( metadata_ ) )
2020-06-20 15:11:37 +03:00
{ }
} ;
2020-07-06 13:37:39 +03:00
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE ( person_without_private_data_2 , age , name , metadata )
2020-07-19 20:12:13 +03:00
class person_with_private_alphabet
{
2020-07-19 20:17:03 +03:00
public :
2020-07-19 20:12:13 +03:00
bool operator = = ( const person_with_private_alphabet & other )
{
2020-07-19 20:17:03 +03:00
return std : : tie ( a , b , c , d , e , f , g , h , i , j , k , l , m , n , o , p , q , r , s , t , u , v , w , x , y , z ) = =
2020-07-19 20:12:13 +03:00
std : : tie ( other . a , other . b , other . c , other . d , other . e , other . f , other . g , other . h , other . i , other . j , other . k , other . l , other . m , other . n , other . o , other . p , other . q , other . r , other . s , other . t , other . u , other . v , other . w , other . x , other . y , other . z ) ;
}
2020-07-19 20:17:03 +03:00
private :
2020-07-19 20:12:13 +03:00
int a ;
int b ;
int c ;
int d ;
int e ;
int f ;
int g ;
int h ;
int i ;
int j ;
int k ;
int l ;
int m ;
int n ;
int o ;
int p ;
int q ;
int r ;
int s ;
int t ;
int u ;
int v ;
int w ;
int x ;
int y ;
int z ;
NLOHMANN_DEFINE_TYPE_INTRUSIVE ( person_with_private_alphabet , a , b , c , d , e , f , g , h , i , j , k , l , m , n , o , p , q , r , s , t , u , v , w , x , y , z )
} ;
class person_with_public_alphabet
{
2020-07-19 20:17:03 +03:00
public :
2020-07-19 20:12:13 +03:00
bool operator = = ( const person_with_public_alphabet & other )
{
2020-07-19 20:17:03 +03:00
return std : : tie ( a , b , c , d , e , f , g , h , i , j , k , l , m , n , o , p , q , r , s , t , u , v , w , x , y , z ) = =
2020-07-19 20:12:13 +03:00
std : : tie ( other . a , other . b , other . c , other . d , other . e , other . f , other . g , other . h , other . i , other . j , other . k , other . l , other . m , other . n , other . o , other . p , other . q , other . r , other . s , other . t , other . u , other . v , other . w , other . x , other . y , other . z ) ;
}
2020-07-19 20:17:03 +03:00
2020-07-19 20:12:13 +03:00
int a ;
int b ;
int c ;
int d ;
int e ;
int f ;
int g ;
int h ;
int i ;
int j ;
int k ;
int l ;
int m ;
int n ;
int o ;
int p ;
int q ;
int r ;
int s ;
int t ;
int u ;
int v ;
int w ;
int x ;
int y ;
int z ;
} ;
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE ( person_with_public_alphabet , a , b , c , d , e , f , g , h , i , j , k , l , m , n , o , p , q , r , s , t , u , v , w , x , y , z )
2020-06-20 15:11:37 +03:00
} // namespace persons
TEST_CASE_TEMPLATE ( " Serialization/deserialization via NLOHMANN_DEFINE_TYPE_INTRUSIVE " , T ,
persons : : person_with_private_data ,
persons : : person_without_private_data_1 ,
persons : : person_without_private_data_2 )
{
SECTION ( " person " )
{
// serialization
2020-06-30 15:26:52 +03:00
T p1 ( " Erik " , 1 , { { " haircuts " , 2 } } ) ;
CHECK ( json ( p1 ) . dump ( ) = = " { \" age \" :1, \" metadata \" :{ \" haircuts \" :2}, \" name \" : \" Erik \" } " ) ;
2020-06-20 15:11:37 +03:00
// deserialization
T p2 = json ( p1 ) ;
CHECK ( p2 = = p1 ) ;
// roundtrip
CHECK ( T ( json ( p1 ) ) = = p1 ) ;
CHECK ( json ( T ( json ( p1 ) ) ) = = json ( p1 ) ) ;
// check exception in case of missing field
json j = json ( p1 ) ;
j . erase ( " age " ) ;
T p3 ;
CHECK_THROWS_WITH_AS ( p3 = json ( j ) , " [json.exception.out_of_range.403] key 'age' not found " , json : : out_of_range ) ;
}
}
2020-07-19 20:12:13 +03:00
TEST_CASE_TEMPLATE ( " Serialization/deserialization of classes with 26 public/private member variables via NLOHMANN_DEFINE_TYPE_INTRUSIVE and NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE " , T ,
persons : : person_with_private_alphabet ,
persons : : person_with_public_alphabet )
{
2020-07-19 20:17:03 +03:00
SECTION ( " alphabet " )
2020-07-19 20:12:13 +03:00
{
{
2020-07-19 20:17:03 +03:00
T obj1 ;
2020-07-19 20:12:13 +03:00
nlohmann : : json j = obj1 ; //via json object
T obj2 ;
j . get_to ( obj2 ) ;
2020-07-19 23:25:27 +03:00
CHECK ( obj1 = = obj2 ) ;
2020-07-19 20:12:13 +03:00
}
{
2020-07-19 20:17:03 +03:00
T obj1 ;
2020-07-19 20:12:13 +03:00
nlohmann : : json j1 = obj1 ; //via json string
std : : string s = j1 . dump ( ) ;
nlohmann : : json j2 = nlohmann : : json : : parse ( s ) ;
T obj2 ;
j2 . get_to ( obj2 ) ;
2020-07-19 23:25:27 +03:00
CHECK ( obj1 = = obj2 ) ;
2020-07-19 20:12:13 +03:00
}
{
2020-07-19 20:17:03 +03:00
T obj1 ;
2020-07-19 20:12:13 +03:00
nlohmann : : json j1 = obj1 ; //via msgpack
std : : vector < uint8_t > buf = nlohmann : : json : : to_msgpack ( j1 ) ;
nlohmann : : json j2 = nlohmann : : json : : from_msgpack ( buf ) ;
T obj2 ;
j2 . get_to ( obj2 ) ;
2020-07-19 23:25:27 +03:00
CHECK ( obj1 = = obj2 ) ;
2020-07-19 20:12:13 +03:00
}
{
2020-07-19 20:17:03 +03:00
T obj1 ;
2020-07-19 20:12:13 +03:00
nlohmann : : json j1 = obj1 ; //via bson
std : : vector < uint8_t > buf = nlohmann : : json : : to_bson ( j1 ) ;
nlohmann : : json j2 = nlohmann : : json : : from_bson ( buf ) ;
T obj2 ;
j2 . get_to ( obj2 ) ;
2020-07-19 23:25:27 +03:00
CHECK ( obj1 = = obj2 ) ;
2020-07-19 20:12:13 +03:00
}
{
2020-07-19 20:17:03 +03:00
T obj1 ;
2020-07-19 20:12:13 +03:00
nlohmann : : json j1 = obj1 ; //via cbor
std : : vector < uint8_t > buf = nlohmann : : json : : to_cbor ( j1 ) ;
nlohmann : : json j2 = nlohmann : : json : : from_cbor ( buf ) ;
T obj2 ;
j2 . get_to ( obj2 ) ;
2020-07-19 23:25:27 +03:00
CHECK ( obj1 = = obj2 ) ;
2020-07-19 20:12:13 +03:00
}
{
2020-07-19 20:17:03 +03:00
T obj1 ;
2020-07-19 20:12:13 +03:00
nlohmann : : json j1 = obj1 ; //via ubjson
std : : vector < uint8_t > buf = nlohmann : : json : : to_ubjson ( j1 ) ;
nlohmann : : json j2 = nlohmann : : json : : from_ubjson ( buf ) ;
T obj2 ;
j2 . get_to ( obj2 ) ;
2020-07-19 23:25:27 +03:00
CHECK ( obj1 = = obj2 ) ;
2020-07-19 20:12:13 +03:00
}
}
}