Я фанат Джексона Маппера в Java, и я немного потерян без него в php. Я хотел бы эквивалент.
Пока что мне ближе всего это, однако, требуется, чтобы поля были объявлены как публичные, и я не хочу этого делать:
https://github.com/netresearch/jsonmapper
Я хочу что-то, что делает все, что делает, с такого рода кодом:
<?php
class Contact
{
/**
* Full name
* @var string
*/
public $name; //<- I want this to be private
/**
* @var Address //<- and this
*/
public $address;
}
class Address
{
public $street;<- and this
public $city;<- and this
public function getGeoCoords()
{
//do something with the $street and $city
}
}
$json = json_decode(file_get_contents('http://example.org/bigbang.json'));
$mapper = new JsonMapper();
$contact = $mapper->map($json, new Contact());
Джсон из file_get_contents
:
{
'name':'Sheldon Cooper',
'address': {
'street': '2311 N. Los Robles Avenue',
'city': 'Pasadena'
}
}
Поэтому я не хочу писать отдельных конструкторов или что-то индивидуальное вообще.
Я уверен, что будет что-то, что делает это из коробки, используя отражение?
Это может быть достигнуто очень легко и красиво, используя Closures.
Нет даже необходимости создавать сеттер-функции.
<?php
class A {
private $b;
public $c;
function d() {
}
}
$data = [
'b' => 'b-value',
'c' => 'c-value',
'd' => 'function',
];
class JsonMapper {
public function map( $data, $context ) {
$json_mapper = function() use ( $data ) {
foreach ($data as $key => $value) {
if ( property_exists( $this, $key ) ) {
$this->{$key} = $value;
}
}
};
$json_mapper = $json_mapper->bindTo( $context, $context );
$json_mapper();
return $context;
}
}
$mapper = new JsonMapper();
$a = $mapper->map( $data, new A );
print_r($a);
Вы можете предоставить метод установки для защищенных и закрытых переменных:
public function setName($name)
{
$this->name = $name;
}
JsonMapper будет автоматически использовать его.
Начиная с версии 1.1.0 JsonMapper поддерживает отображение частных и защищенных свойств.
Извините, мне не хватает «репутации», поэтому я не могу добавить комментарий.
Я использую Java всего несколько месяцев, но, насколько я понимаю, все ваши классы на Java будут иметь геттеры и настройки, и именно так Джексон может установить значение частного свойства.
Я подозреваю, что для того, чтобы сделать то же самое в PHP, вам нужно сделать свои свойства приватными и создать методы getter и setter …
public function setName($name) {
$this->name = name;
}
Затем в вашем Mapper используйте рефлексию, чтобы вызвать сеттер.
Я бы сделал так, чтобы посмотреть на ключи, которые есть в JSON, и попытаться составить имя метода.
Например, если в JSON есть ключ с именем «name» …
$className = "Contact";
$object = json_decode($jsonResponse);
$classObject = new $className();
foreach ($object as $key => $value) {
$methodName = "set" . ucfirst($key);
if (method_exists($classObject, $methodName)) {
$classObject->$methodName($value);
}
}
Вышесказанное может быть не совсем правильным, но я надеюсь, что это даст вам представление.
Чтобы расширить вышесказанное, я собрал следующий пример, который, кажется, делает то, что вам нужно?
class Contact {
private $name;
private $telephone;
public function setName($name) {
$this->name = $name;
}
public function setTelephone($telephone) {
$this->telephone = $telephone;
}
public function getName() {
return $this->name;
}
public function getTelephone() {
return $this->telephone;
}
}
class Mapper {
private $jsonObject;
public function map($jsonString, $object) {
$this->jsonObject = json_decode($jsonString);
if (count($this->jsonObject) > 0) {
foreach ($this->jsonObject as $key => $value) {
$methodName = "set" . ucfirst($key);
if (method_exists($object, $methodName)) {
$object->$methodName($value);
}
}
}
return $object;
}
}
$myContact = new stdClass();
$myContact->name = "John Doe";
$myContact->telephone = "0123 123 1234";
$jsonString = json_encode($myContact);
$mapper = new Mapper();
$contact = $mapper->map($jsonString, new Contact());
echo "Name: " . $contact->getName() . "<br>";
echo "Telephone: " . $contact->getTelephone();