2014-10-20 231 views
1

我想打印任何JSON对象作为简单的HTML表单输入名称属性作为点符号JSON属性的Xpath。打印多维JSON作为HTML格式的输入名称为xpath的属性

到目前为止,它的工作原理,但我失去了最初的

function printInp($title, $pre, $val, $rulekey = false) { 
     $html = "<label for='$pre'>$pre</label>"; 
     $html .= "<input name='$pre' value='$val' type='text' />"; 
     return $html; 
    } 


    function printForm($title, $item, $pre = '', $rulekey=false) { 
     if (!is_array($item)) { 
      echo printInp($title, $pre, $item, $rulekey); 
     } else { 
      foreach ($item as $key => $val) { 
       $pre = (empty($pre)) ? $key : $pre . '.' . $key;      
       if (is_array($val)) { 
        printForm($title, $val, $pre, $key); 
       } else { 
        echo printInp($title, $pre, $val, $key); 
       } 
       $pre = ''; 
      } 
     } 
    } 

    $jsonStr = json_decode('[{"id":12,"name":"live music","icon":{"url":null,"thumb":{"url":null},"ios_profile":{"url":null},"medium":{"url":null}},"display_name":null,"top_level":false}]', TRUE); 
    echo printForm('test', $jsonStr); 

版画的轨迹......

<label for='id'>id</label><input name='id' value='12' type='text' class='' /> 
    <label for='name'>name</label><input name='name' value='live music' type='text' class='' /> 
    <label for='icon.url'>icon.url</label><input name='icon.url' value='' type='text' class='' /> 
    <label for='thumb.url'>thumb.url</label><input name='thumb.url' value='' type='text' class='' /> 
    <label for='ios_profile.url'>ios_profile.url</label><input name='ios_profile.url' value='' type='text' class='' /> 
    <label for='medium.url'>medium.url</label><input name='medium.url' value='' type='text' class='' /> 
    <label for='display_name'>display_name</label><input name='display_name' value='' type='text' class='' /> 
    <label for='top_level'>top_level</label><input name='top_level' value='' type='text' class='' /> 

问题BEING:我迷失了顶级节点名称 - 在这个“图标”案例 - 当我遍历数组。

它应该是这样的

<label for='id'>id</label><input name='id' value='12' type='text' class='' /> 
    <label for='name'>name</label><input name='name' value='live music' type='text' class='' /> 
    <label for='icon.url'>icon.url</label><input name='icon.url' value='' type='text' class='' /> 
    <label for='icon.thumb.url'>icon.thumb.url</label><input name='icon.thumb.url' value='' type='text' class='' /> 
    <label for='icon.ios_profile.url'>icon.ios_profile.url</label><input name='icon.ios_profile.url' value='' type='text' class='' /> 
    <label for='icon.medium.url'>icon.medium.url</label><input name='icon.medium.url' value='' type='text' class='' /> 
    <label for='display_name'>display_name</label><input name='display_name' value='' type='text' class='' /> 
    <label for='top_level'>top_level</label><input name='top_level' value='' type='text' class='' /> 

(我将接受任何语言的答案)

+0

如果你的json对象的级别将会是无限的,那么你可能需要递归地遍历它们,如果这些级别将被修复,那么只需检查当前级别是否仍然是一个数组。 – Ghost 2014-10-20 00:38:23

+0

@Ghost,关卡可以去深达4层(但我不想围绕这个限制设计)。我目前正在递归地做这件事。 – 2014-10-20 02:31:59

回答

3

这个答案将是PHP。由于@Ghost已经评论并且您确认了,这需要用递归来解决。但是,在您的方案中,递归可能有点麻烦。

那么你可以在PHP做的是与RecursiveIteratorIterator容易合作,把递归到您的平板输入元素的列表。

让我们从第一个简单的例子开始,它仍然是不完整的,但显示它是如何工作的。这和下面的例子将利用你的JSON字符串,但我不同的命名变量一点:

$jsonStr 
    = <<<JSON 
[ 
    { 
     "id" : 12, 
     "name": "live music", 
     "icon": { 
        "url"  : null, 
        "thumb"  : {"url": null}, 
        "ios_profile": {"url": null}, 
        "medium"  : {"url": null} 
       }, 
     "display_name": null, 
     "top_level" : false 
    } 
] 
JSON; 
$json = json_decode($jsonStr, true); 

所以展示如何利用RecursiveIteratorIterator这里的把你的递归树结构的第一个例子,你有在JSON字符串成扁平列表:

$it = new RecursiveArrayIterator($json); 
$rit = new RecursiveIteratorIterator($it); 
foreach ($rit as $key => $value) { 
    printf("%s: %s\n", $key, var_export($value, 1)); 
} 

此输出该树的所有叶节点与其他后键和值之一:

id: 12 
name: 'live music' 
url: NULL 
url: NULL 
url: NULL 
url: NULL 
display_name: NULL 
top_level: false 

它仍然没有通往每个节点的路径,你也在寻找。但它已经表明,树已经变成了一个列表。

要立即获得的路径的每个节点,RecursiveIteratorIterator允许通过其getSubIterator方法遍历所有密钥到当前节点的迭代器。以深度信息纳入考虑,该路径可以容易地产生:

foreach ($rit as $key => $value) { 
    $jsonPathSegments = []; 
    for ($level = 0; $level <= $rit->getDepth(); $level++) { 
     $jsonPathSegments[$level] = $rit->getSubIterator($level)->key(); 
    } 
    $jsonPath = implode('.', $jsonPathSegments); 

    printf("%s: %s\n", $jsonPath, var_export($value, 1)); 
} 

现在这产生以下输出:

0.id: 12 
0.name: 'live music' 
0.icon.url: NULL 
0.icon.thumb.url: NULL 
0.icon.ios_profile.url: NULL 
0.icon.medium.url: NULL 
0.display_name: NULL 
0.top_level: false 

现在示出,即获得到每个节点的路径是容易可行的。这仍然需要一些微调,因为您实际上不需要第一个(0)级别的密钥。这可以通过初始化$levelfor循环进行到1

for ($level = 1; $level <= $rit->getDepth(); $level++) { 
       ^

更新的输出:

id: 12 
name: 'live music' 
icon.url: NULL 
icon.thumb.url: NULL 
icon.ios_profile.url: NULL 
... 

所以这解决了已经潜在的问题,但也可以让你以后关心的输出。包裹该向上和利用__toString甚至允许您轻松地创建一个HTML插件:

echo new JsonForm($jsonStr); 

产生以下示例性输出:

/** 
* Class JsonForm 
* 
* Exemplary HTML Widget 
*/ 
class JsonForm extends RecursiveIteratorIterator 
{ 
    private $json; 
    public function __construct($json) { 
     if (is_string($json) || is_object($json) && method_exists($json, '__toString')) { 
      $json = json_decode($json); 
     } 
     parent::__construct(new RecursiveArrayIterator($json)); 
    } 

    public function getJsonPath() { 
     $jsonPathSegments = []; 
     for ($level = 1; $level <= $this->getDepth(); $level++) { 
      $jsonPathSegments[$level] = $this->getSubIterator($level)->key(); 
     } 
     $jsonPath = implode('.', $jsonPathSegments); 

     return $jsonPath; 
    } 

    public function __toString() { 
     $html = ''; 
     foreach ($this as $value) { 
      $path = $this->getJsonPath(); 
      $html .= sprintf(
       '<label for="%1$s">%1$s</label><input name="%1$s" value="%2$s" type="text" />'."\n", 
       htmlspecialchars($path), htmlspecialchars($value) 
      ); 
     } 
     return $html; 
    } 
} 

该封装或以简单的呼叫所需要的处理逻辑

<label for="id">id</label><input name="id" value="12" type="text" /> 
<label for="name">name</label><input name="name" value="live music" type="text" /> 
<label for="icon.url">icon.url</label><input name="icon.url" value="" type="text" /> 
<label for="icon.thumb.url">icon.thumb.url</label><input name="icon.thumb.url" value="" type="text" /> 
<label for="icon.ios_profile.url">icon.ios_profile.url</label><input name="icon.ios_profile.url" value="" type="text" /> 
<label for="icon.medium.url">icon.medium.url</label><input name="icon.medium.url" value="" type="text" /> 
<label for="display_name">display_name</label><input name="display_name" value="" type="text" /> 
<label for="top_level">top_level</label><input name="top_level" value="" type="text" /> 

我希望这给出一些指示。它显示了如何通过PHP中的RecursiveIteratorIterator(参考:How does RecursiveIteratorIterator work in PHP?)的操作将树结构视为平面列表。

路径的基于子项的递归结构该建筑中

。很可能有更多这样的例子。

+0

BRILLIANT!谢谢!! – 2014-10-26 15:38:38