How to save a JSON string in MongoDB?

Imagine you have an API which takes a JSON string as the input. Unlike relational databases, MongoDB will allow you to directly save JSON data. Wait .. there is still a little bit of work since the JSON data is stored in a string whereas MongoDB expects it to be in an array or an object.

There are two options.

Option 1: Decode to a JSON object and save

You can use the json_decode() function to convert the string to an object or array and this can be directly inserted to the MongoDB. (Of course, Mongo will internally convert it to a BSON format, which is not relevant to our discussion).

Here is the PHP code if you are taking this approach.

$country = '{"name" : "Mauritius", "population" : "1.2 million", "languages" : {"primary" : "english", "secondary" : "french"}, "history" : [{"Portuguese": "1507 - 1513"}, {"Dutch": "1638 - 1710"}, {"French" : "1710 - 1810"}, {"British": "1810 - 1968"}]}';

$connection = new Mongo();

$countryCollection = $connection->test->countries;

$countryCollection->insert(json_decode($country));

How do you validate the JSON data in this case? You could define a JSON schema (much like XML schema) and use a PHP library like jsonschema to do the validation.

Option 2: Use an intermediate object

In this approach, you need to convert the JSON string to an array or an object and then assign to an intermediate object. This intermediate object can do validation of the data as well provide additional methods to manipulate the data.  The code would be as follows:
 
class Country {
 public function __construct(array $obj) {
  foreach($obj as $key => $value) {
   $this->$key = $value;
  }
 }

 public function printHistory() {
  
  foreach ($this->history as $history) {
   foreach ($history as $empire => $year) {
    print $empire . " (" . $year. ")\n";
   }
  }
 }

 public function validate() {
  //add validation code here
 }
}

$country = '{"name" : "Mauritius", "population" : "1.2 million", "languages" : {"primary" : "english", "secondary" : "french"}, "history" : [{"Portuguese": "1507 - 1513"}, {"Dutch": "1638 - 1710"}, {"French" : "1710 - 1810"}, {"British": "1810 - 1968"}]}';

$countryObj = new Country(json_decode($country, true));

$countryObj->printHistory();

$connection = new Mongo();
$countryCollection = $connection->test->countries;

$countryCollection->insert($countryObj);


Please note that we are copying the JSON decoded data to the Country object so that we can easily access all attributes. If you are concerned about the space, you could assign the JSON decoded data as an attribute of the Country object and go from there.

Comments