Generate random JSON data using C++

In this tutorial, we are going to learn what is JSON data, what are the advantages of JSON data, and how we can create our own JSON data using C++.

JSON is a widely used data structure for sharing data on the internet. It is lightweight data and independent of language. It is easy to understand and create. 

Types of data that JSON consists of are -: 

  1. Numbers 
  2. Strings 
  3. Boolean 
  4. Array 
  5. Null
  6. Object 

 

Objects and null are referred to as complex data types whereas numbers, strings, Boolean are referred to as simple data type  

Given below are some advantages of JSON -: 

  1. Syntax is easy and light that’s why it is fast and efficient  
  2. It is compatible with a wide range of browsers and doesn’t require much effort to make it compatible with all browsers. 

 

Code for generating random JSON data

#include "json.hpp"
#include<iostream>
#include<random>

#define MAX_STRING_LENGTH 10
#define MAXIMUM_KEYS 7
#define MINIMUM_KEYS 4
#define MAX_JSON_DEPTH 4
#define MAX_VALUE_RANDOM_INTEGER 50
#define MIN_VALUE_RANDOM_INTEGER 5
#define MAX_VECTOR_LENGTH 9

/**Different value types for keys of JSON*/
#define BOOLEAN 0
#define INTEGER 1
#define STRING 2
#define VECTOR 3
#define JSON 4

#define INCLUDE_JSON 0,4
#define EXCLUDE_JSON 0,3
#define INTEGER_TYPE 1


using json = nlohmann::json;
using namespace std;

/**String of characters to generate random string*/
const string CHARACTERS = 
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

/** Used to generate uniformly distributed random number*/
    random_device rd;

/**Random number engine*/
mt19937 generator(rd());

/**Important Function Declaration*/
json generateRandomJson(int);
int generateRandomIntegerWithRange(int,int);
int assignValueTypeToJsonKey(int);
void assignKeyValuePairToJson(int,json &,int);




uniform_int_distribution<int> generateUniformDistributionWithRange
(int lowerBound,int upperBound) {

    /**Uniformly distributed random integer generator between
       two bounds*/
    uniform_int_distribution<int> distribution(lowerBound,upperBound);

    return distribution;
}

/**This function generates a random integer between two numbers */
int generateRandomIntegerWithRange(int lowerBound, int upperBound) {
    return generateUniformDistributionWithRange(lowerBound,
    upperBound)(generator);
}

string generateRandomString() {
    string randomString;

    /**This variable stores the random value of length of string*/
    int randomLength = 
    generateRandomIntegerWithRange(1,MAX_STRING_LENGTH);

    /**This variable stores the generator used to generate
       random number between two values*/
    uniform_int_distribution<int> characterDistribution = 
    generateUniformDistributionWithRange(0,CHARACTERS.size()-1);

    for(int index = 0; index < randomLength; index++) {
        /**Each iteration adds a random character to string 
           using global string CHARACTERS*/
        randomString+= CHARACTERS[characterDistribution(generator)];
    }

    return randomString;

}

bool generateRandomBoolean() {
    if(generateRandomIntegerWithRange(0,1)){
        return true;
    }

    return false;
}


int generateRandomInteger(){
    return 
    generateRandomIntegerWithRange(MIN_VALUE_RANDOM_INTEGER,
    MAX_VALUE_RANDOM_INTEGER);
}

int getRandomVectorLength() {
   return generateRandomIntegerWithRange(1,MAX_VECTOR_LENGTH);
}

vector<int> generateRandomIntegerVector() {
    vector<int> v;

    int vectorLength = getRandomVectorLength();

    for(int index=0; index < vectorLength ; index++){
        v.push_back(generateRandomInteger());
    }

    return v;
}

vector<string> generateRandomStringVector(){
    vector<string> v;

    int vectorLength = getRandomVectorLength();

    for(int index=0; index < vectorLength ; index++){
        v.push_back(generateRandomString());
    }

    return v;
}

/**This function returns a random integer that determines the value type
  ( example : boolean, integer etc )for a key */
int assignValueTypeToJsonKey(int jsonDepth)
{
      int valueType;

      /**If this condition is true, then JSON object cannot be 
         value type*/
      if(jsonDepth > MAX_JSON_DEPTH){
            valueType = generateRandomIntegerWithRange(EXCLUDE_JSON);
        }

        else{
            valueType = generateRandomIntegerWithRange(INCLUDE_JSON);
        }

        return valueType;
}

/**This function generates either 0 or 1.
   If 0 is generated, then vector value type is integer.
   Otherwise vector value type is string*/

bool getVectorType(){

return generateRandomBoolean();

}

/**This function generates key value pair for JSON*/

void assignKeyValuePairToJson(int valueType,json &t, int jsonDepth){
       if(valueType==BOOLEAN){
            t[generateRandomString()]=generateRandomBoolean();
        }

        else if(valueType==INTEGER){
            t[generateRandomString()]=generateRandomInteger();
        }

        else if(valueType==STRING){
            t[generateRandomString()]=generateRandomString();
        }

        else if(valueType==VECTOR){
            bool vectorType = getVectorType();

            if(vectorType == INTEGER_TYPE){
               t[generateRandomString()]=generateRandomIntegerVector();
            }

            else{
                t[generateRandomString()]=generateRandomStringVector();
            }
        }

        else{
            /**When a value type is another JSON object, then we 
               increase the jsonDepth variable by one.
               This is because we are creating another JSON object as a
               value for a key inside the present JSON object */
            t[generateRandomString()]=generateRandomJson(jsonDepth+1);
        }
}

/** This function generates the JSON object */

json generateRandomJson(int jsonDepth) {
    json t;

    int numberOfKeys =
    generateRandomIntegerWithRange(MINIMUM_KEYS,
    MAXIMUM_KEYS);

    for(int index =0;index < numberOfKeys; index++){
        /**This variable stores what value type 
           ( example : boolean, integer etc ) will the key store */
        int valueType = assignValueTypeToJsonKey(jsonDepth);

        /**This function call generates the key value pair 
           inside JSON object */
       assignKeyValuePairToJson(valueType,t,jsonDepth);
    }

    return t;
}

int main(){

    /**Initial json depth*/
    int jsonDepth = 1;

    /**Function call to generate random json object*/
    json j=generateRandomJson(jsonDepth);

    /**Used to print json data in the form of a string
       Serialized pretty print*/
    string ans = j.dump(4);
    cout<<ans;

    return 0;
}


External Library Used

Nlohmann Json library has been used in the code ( json.hpp ). 

 

Introduction of the code 

This code generates random JSON data. This means that the output contains any random number of key-value pairs where value can be of any type. The types of values included in the code are as follows:  

  1. Boolean  
  2. Integer 
  3. String 
  4. Array 
  5. JSON Object 

 

Function functionality

1. generateUniformDistributionWithRange(int lowerBound, int upperBound)  

uniform_int_distribution<int> generateUniformDistributionWithRange(int lowerBound, int upperBound) {

/**Uniformly distributed random integer generator between two bounds*/
uniform_int_distribution<int> distribution(lowerBound,upperBound);

return distribution;
}

This function generates a uniform_int_distribtution object. This object can be used to generate a uniformly distributed random number between two numbers ( lower bound and upper bound ). These two numbers are provided in the function as arguments.  

 

 2. generateRandomIntegerWithRange()  

int generateRandomIntegerWithRange(int lowerBound, int upperBound) {
    return generateUniformDistributionWithRange(lowerBound,upperBound)(generator);
}

This function generates a uniformly distributed random integer between two numbers using the uniform_int_distribution object (this object is generated by the function explained in point 1). 

 

3.generateRandomString()

string generateRandomString() {
string randomString;

/**This variable stores the random value of length of string*/
int randomLength = generateRandomIntegerWithRange(1,MAX_STRING_LENGTH);

/**This variable stores the generator used to generate random number between two values*/
uniform_int_distribution<int> characterDistribution = generateUniformDistributionWithRange(0,CHARACTERS.size()-1);

   for(int index = 0; index < randomLength; index++) {
   /**Each iteration adds a random character to string using global string CHARACTERS*/
   randomString+= CHARACTERS[characterDistribution(generator)];
   }

 return randomString;

}

This function generates a random string with a random length using the above two functions and using a global declared string named “CHARACTERS”. This string includes all the lowercase and uppercase English characters along with numbers.

  

4. Global Character String

/**String of characters to generate random string*/
const string CHARACTERS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

For every iteration of the loop, one character is picked randomly from the global string “CHARACTERS” and added to the random string.

 

Implementation

int main(){
/**Initial json depth*/
int jsonDepth = 1;

/**Function call to generate random json object*/
json j=generateRandomJson(jsonDepth);

/**Used to print json data in the form of a string
   Serialized pretty print*/
string ans = j.dump(4);
cout<<ans;
return 0;
}

In the main function, function “generateRandomJson()” is called which would generate the “Nlohmann” JSON object.  JSON depth is the variable that tells how deep the JSON object is nested (nesting means creating JSON object inside a JSON object). The variable “jsonDepth” is assigned value one as there is no nesting initially.  

 

#define MAX_STRING_LENGTH 10
#define MAXIMUM_KEYS 7
#define MINIMUM_KEYS 4
#define MAX_JSON_DEPTH 4
#define MAX_VALUE_RANDOM_INTEGER 50
#define MIN_VALUE_RANDOM_INTEGER 5
#define MAX_VECTOR_LENGTH 9

/**Different value types for keys of JSON*/
#define BOOLEAN 0
#define INTEGER 1
#define STRING 2
#define VECTOR 3
#define JSON 4

#define INCLUDE_JSON 0,4
#define EXCLUDE_JSON 0,3
#define INTEGER_TYPE 1
Integer Value Type
0 Boolean
1 Integer
2 String
3 Array
4 JSON Object

 

json generateRandomJson(int jsonDepth) {
    json t;

    int numberOfKeys = generateRandomIntegerWithRange(MINIMUM_KEYS,MAXIMUM_KEYS);

    for(int index =0;index < numberOfKeys; index++){
        /**This variable stores what value type ( example : boolean, integer etc ) will 
           the key store */
        int valueType = assignValueTypeToJsonKey(jsonDepth);

        /**This function call generates the key value pair inside JSON object */
        assignKeyValuePairToJson(valueType,t,jsonDepth);
    }

    return t;
}

In the function for every iteration of the loop, the value type (the value types explained above) for the key is generated randomly by calling the function “assignValueTypeToJsonKey()”.  

/**This function returns a random integer that determines the value type 
    ( example : boolean, integer etc ) for a key */
int assignValueTypeToJsonKey(int jsonDepth)
{
   int valueType;

   /**If this condition is true, then JSON object cannot be value type*/
   if(jsonDepth > MAX_JSON_DEPTH){
   valueType = generateRandomIntegerWithRange(EXCLUDE_JSON);
   }

   else{
   valueType = generateRandomIntegerWithRange(INCLUDE_JSON);
   }

  return valueType;
}

There is an upper limit on the depth up to which value type “JSON object” is allowed because we want to avoid infinite nesting of JSON objects. This is taken care of in the function “assignValueTypeToJsonKey()”. The variable “jsonDepth” is incremented when we nest a new JSON object inside the present JSON object. When this variable becomes greater than the maximum depth allowed ( MAX_JSON_DEPTH ), then the JSON object type is not included in the value type to avoid infinite nesting. 

 /**This function call generates the key value pair inside JSON object */
        assignKeyValuePairToJson(valueType,t,jsonDepth);

After getting the value type, the function “assignKeyValuePairToJson()” is called which generates key-value pairs of the JSON object randomly and also inserts the generated value to the JSON object.  

Nlohmann JSON object is implemented such that for adding a key-value pair inside the object, the key type should always be a string and the value can be of any type. (example: boolean, integer, vector, map, etc) 

 

/**This function generates key value pair for JSON*/
void assignKeyValuePairToJson(int valueType,json &t, int jsonDepth){
   if(valueType==BOOLEAN){
   t[generateRandomString()]=generateRandomBoolean();
   }

   else if(valueType==INTEGER){
   t[generateRandomString()]=generateRandomInteger();
   }

   else if(valueType==STRING){
   t[generateRandomString()]=generateRandomString();
   }

   else if(valueType==VECTOR){
   bool vectorType = getVectorType();

     if(vectorType == INTEGER_TYPE){
     t[generateRandomString()]=generateRandomIntegerVector();
     }

     else{
     t[generateRandomString()]=generateRandomStringVector();
     }
   }

  else{
  /**When value type is another JSON object, then we increase the jsonDepth variable by one.
     This is because we are creating another JSON object as a value for a key inside the 
     present JSON object */
  t[generateRandomString()]=generateRandomJson(jsonDepth+1);
  }
}

Inside the function, the key is generated by calling the function “generateRandomString()” and the function call corresponding to the value type ( obtained earlier ) is made to generate the value for the key.

 

ValueType

 

 Function Name

 

Boolean

 

 generateRandomBoolean()

 

Integer

 

 generateRandomInteger()

 

String

 

 generateRandomString()

 

Array

 

 generateRandomIntegerVector()  OR generateRandomStringVector()

 

JSON Object

 

generateRandomJson()

 

 

Let us take an example that the value type is Array. In Nlohmann JSON library implementation, adding an array to the key requires taking the data structure for the key as a vector. Vector can contain different types of values ( example: string, integer, float, etc ). In the code, only two types ( string and integer ) are included. Anyone type ( either string or integer ) out of the two is selected randomly and the corresponding function for the selected type is called ( generateRandomIntegerVector() OR generateRandomStringVector() ) to generate the value which is a vector that is inserted inside the JSON object.    

 

On the other hand, if the value type is a JSON object, then this means that a new JSON object will be nested inside the present JSON object. Therefore the function “generateRandomJson” is called again and the value of the variable “jsonDepth” is incremented and passed as an argument. As explained earlier, this variable along with the global variable “MAX_JSON_DEPTH” helps to avoid infinite nesting.

 

/**Used to print json data in the form of a string
   Serialized pretty print*/
string ans = j.dump(4);
cout<<ans;

return 0;

Nlohmann JSON library has a dump function that converts the JSON object into a string. If number “4” is passed as an argument to the dump function, then the string generated will be serialized and will include pretty print.

 

Output

 



    "78Cs9": [ 

        "1ob", 

        "q" 

    ], 

    "7l": true, 

    "9Xpjc": "O9n6", 

    "faJtUmfcF7": { 

        "8LuZV": false, 

        "ShXC": "HUC8", 

        "ewaMigsSZK": { 

            "1j": [ 

                "xlb8B3LVlY", 

                "QqQM4l", 

                "Cx", 

                "ADPOS" 

            ], 

            "Cko2Ww": "dh3qx11p1V", 

            "IzMIBg6ud": { 

                "1TDQ": 39, 

                "6hDjrp": "SBZjM50", 

                "Ao": { 

                    "O3iOjVe2l": "LxykgVBYF", 

                    "SaPm8QyM30": [ 

                        "1JjlJ9B", 

                        "7z", 

                        "MAUF", 

                        "N2R7KUpKlp", 

                        "hdTeL", 

                        "goX0AISC", 

                        "wKEehueC" 

                    ], 

                    "yHJNbs": "dYGwZSKL", 

                    "z7scX": false 

                }, 

                "Il4S": "wHrS", 

                "hPrQ": { 

                    "5cCC": true, 

                    "MAZ": 20, 

                    "SIsF": false, 

                    "XLND": "clUDyL3yP", 

                    "uIon5p": [ 

                        "D", 

                        "1gSfEgoId" 

                    ] 

                }, 

                "i7s4XLHWo0": 29, 

                "qm": 11 

            }, 

            "Lo": [ 

                17, 

                46, 

                24, 

                9, 

                48 

            ], 

            "u1vPsCn": "hqTlRz" 

        }, 

        "pqvNn": 20, 

        "t": 14 

    }, 

    "kayOBPR8pd": [ 

        37, 

        39, 

        31, 

        26, 

        19, 

        40 

    ], 

    "q8X0IUK6P": [ 

        "a", 

        "VxyAfJWhm", 

        "4ZK", 

        "aE1A", 

        "x1emTK4L0P", 

        "uHevZq0YH", 

        "j0hGSKDvs", 

        "iyslK", 

        "fAbU4elf" 

    ] 

Leave a Reply

Your email address will not be published. Required fields are marked *