首页 > 解决方案 > php定义的json结构类型提示

问题描述

我想在 php 中输入提示这个 json 结构:

{
  "settings": {
    "signup": {
      "logging": true,
      "forcePrompt": false,
      "completedSteps": [
        1,
        2,
        3
      ]
    },
    "trash": {
      "retentionDays": 30,
      "enabled": true
    }
  }
}

有什么方法可以用一个“设置”类来做到这一点,而不必为每个嵌套属性(注册、垃圾)定义单独的类。

在打字稿中,我可以这样定义:

{
  settings: {
    signup: {
      logging: boolean,
      forcePrompt: boolean,
      completedSteps: number[]
    },
    trash: {
      retentionDays: number,
      enabled: boolean
    }
  }
}

标签: php

解决方案


不,但是您可以自己滚动并非常接近。例如,我有一个作为设置存储并为此扩展ArrayObject的类,所以它是非常标准的非异国情调的东西。

如果您只检查叶属性就可以了(例如“属性 X 是布尔值吗?”而不是“属性 X 作为属性 Y 的子属性是布尔值”?),您可以像这样进行基本类型检查(我'已经稍微缩短了示例代码,你会在这里找到完整的代码):


// Your data

$data = '{

  "settings": {
    "signup": {
      "logging": true,
      "forcePrompt": false,
      "completedSteps": [
        1,
        2,
        3
      ]
    },
    "trash": {
      "retentionDays": 30,
      "enabled": true
    }
  }
}
';

// We'll use this for type hinting

$defaults = '{
    
  "settings": {
    "signup": {
      "logging": true,
      "forcePrompt": false,
      "completedSteps": []
    },
    "trash": {
      "retentionDays": 1,
      "enabled": true
    }
  }
}
';


/**
 * Basic collection object.
 *
 * Usage:
 * ------
 * $collection->acme_social->twitter->client_id 
 */
class Collection extends \ArrayObject {

    /**
     * Initialize and turn all levels of the given
     * array into a collection object.
     * 
     * @param Array $data
     */
    public function __construct(array $data, array $defaults = []) {

        parent::__construct($data, \ArrayObject::ARRAY_AS_PROPS);

        // Turn all arrays into Collections

        $iterator = new \RecursiveIteratorIterator(

            new \RecursiveArrayIterator($this), \RecursiveIteratorIterator::SELF_FIRST
        );

        foreach ($iterator as $key => $value) {
            
            // Evaluate types
                
            array_walk_recursive($defaults, function ($v, $k) use ($key, $value) {

                if ($key == $k) {

                    $expected = gettype($v);
                    $given    = gettype($value);

                    if ($expected != $given) {

                        throw new InvalidArgumentException("{$k} needs to be of type {$expected}, {$given} given.");
                    }
                }
            });

            if (is_array($value)) {

                $iterator->getInnerIterator()->offsetSet($key, new static($value));
            }
        }
    }
}

try {

    $collection = new Collection(json_decode($data, true), json_decode($defaults, true));
}
catch(Exception $e) {

    var_dump($e->getMessage());
}

推荐阅读