ValuesObjectMapper

When we need to convert JSON to a ValuesObject, we can use ValuesObjectMapper. For example, if we have this JSON:

{
  "photo": "XXXX",
  "full_name": "Test Test",
  "educations": [
    {
      "logo": "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7",
      "degree": "NTUU \"KPI\"",
      "field": "bachelor",
      "dates": "2006 – 2011"
    }
  ],
  "skills": [
    {
      "name": "PHP"
    },
    {
      "name": "JavaScript"
    },
    {
      "name": "MySQL"
    }
  ],
  "experiences": [
    {
      "position": "Software Engineer",
      "company": "XXX",
      "dates": "Aug 2014 – Present",
      "logo": "XXXX"
    },
    {
      "position": "Software Engineer",
      "company": "XXXX",
      "dates": "Nov 2013 – Aug 2014",
      "logo": "XXX"
    }
  ],
  "type": "linkedin",
  "url": "https://www.linkedin.com/in/maksym-massalskyi-82009640/"
}

We need to declare the required ValuesObject classes:

class CandidateValuesObject extends ValuesObject
{

    /**
     * @var CandidateEducationValuesObject[]
     */
    private $_educations;

    /**
     * @var SkillValuesObject[]
     */
    private $_skills;

    /**
     * @var CandidateExperienceValuesObject[]
     */
    private $_experiences;


    public function setPhoto(string $url): void
    {
        $this->set('photo', $url);
    } // end setPhoto

    public function setFirstName(string $name): void
    {
        $this->set('name', $name);
    }

    public function setLastName(string $name): void
    {
        $this->set('last_name', $name);
    }

    /**
     * @param CandidateEducationValuesObject[] $items
     */
    public function setEducations(array $items): void
    {
        $this->_educations = $items;
    } // end setEducations

    /**
     * @param CandidateExperienceValuesObject[] $items
     */
    public function setExperiences(array $items): void
    {
        $this->_experiences = $items;
    } // end setExperiences

    /**
     * @param SkillValuesObject[] $items
     */
    public function setSkills(array $items): void
    {
        $this->_skills = $items;
    } // end setSkills
}

class CandidateEducationValuesObject extends ValuesObject
{
    public function setLogo(string $url): void
    {
        $this->set('logo', $url);
    }

    public function setDegree(string $name): void
    {
        $this->set('degree', $name);
    }

    public function setField(string $name): void
    {
        $this->set('field', $name);
    }

    public function setStartYear(int $startYear): void
    {
        $this->set('start_year', $startYear);
    }

    public function setEndYear(int $endYear): void
    {
        $this->set('end_year', $endYear);
    }
}

Now we can convert JSON to ValuesObject:

$mapper = new ValuesObjectMapper();
$candidateValuesObject = $mapper->map($jsonData, 'CandidateValuesObject');

Filters

To modify data during JSON processing, you can use a filter:

$mapper = new ValuesObjectMapper();
$mapper->addFilter('full_name', function (CandidateValuesObject &$valueObject, string $key, $value) {

    list($firstName, $lastName) =  array_map('trim', array_filter(explode(" ", $value)));

    $valueObject->setFirstName($firstName);
    $valueObject->setLastName($lastName);

    return true;
});

$mapper->addFilter(
    'educations__dates',
    function (CandidateEducationValuesObject &$valueObject, string $key, $value) {

    list($startYear, $endYear) = array_map('trim', array_filter(explode("–", $value)));

    $valueObject->setStartYear($startYear);
    $valueObject->setEndYear($endYear);

    return true;
});

$candidateValuesObject = $mapper->map($jsonData, 'CandidateValuesObject');

educations__dates is a selector that indicates the filter should be applied to the dates element in the educations array.