通过反射json字符串到php对象/像jackson mapper

时间:2015-11-10 15:31:39

标签: php json jackson

我是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的Json:

{
    'name':'Sheldon Cooper',
    'address': {
        'street': '2311 N. Los Robles Avenue',
        'city': 'Pasadena'
     }
}

所以我不想写个别的构造函数,或者根本不想编写任何个人构件。

我确定使用反射可以开箱即用吗?

3 个答案:

答案 0 :(得分:1)

使用Closures可以很容易地实现这一点。 甚至不需要创建setter函数。

<?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);

答案 1 :(得分:1)

您可以为受保护变量和私有变量提供setter方法:

public function setName($name)
{
    $this->name = $name;
}

JsonMapper会自动使用它。

从版本1.1.0开始,JsonMapper支持映射私有和受保护的属性。

答案 2 :(得分:0)

抱歉,我没有足够的声誉&#39;所以无法添加评论。

我只使用Java几个月,但我的理解是你的Java课程都会有getter和设置,这就是Jackson能够设置私有财产的价值。

要在PHP中执行相同操作,我怀疑您需要将属性设为私有,并创建getter和setter方法......

public function setName($name) {
    $this->name = name;
}

然后在Mapper中,使用反射来调用setter。

我这样做的方法是查看JSON中的键,并尝试将方法名称放在一起。

例如,如果JSON中的某个键标有&#39; name&#39; ...

$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();