0

问题:我正在尝试遍历 JSON 内容并呈现键值对等结果。

我编写了一些读取 hcl 文件的代码,然后使用 hcldec.Decode 对这些代码进行解码,然后将结果转换为 JSON。这些 hcl 文件为应用程序定义源和目标,如下所示:

源.hcl:

source json "namefile" {
  attr firstName  {
    type = "varchar"
    expr = "$.firstName"
    length = "30"
  }
  attr lastName  {
    type = "varchar"
    expr = "$.lastName"
    length = "40"
  }
  attr gender  {
    type = "varchar"
    expr = "$.gender"
    length = "10"
  }
  attr age {
    type = "varchar"
    expr = "$.age"
    length = "2"
  }
}

目标.hcl

target table {
  cols firstName {
    name=source.json.namefile.attr.firstName.expr
    type=source.json.namefile.attr.firstName.type
    length=source.json.namefile.attr.firstName.length
  }
  cols lastName {
    name=source.json.namefile.attr.lastName.expr
    type=source.json.namefile.attr.lastName.type
    length=source.json.namefile.attr.lastName.length
  }
}

解码是这样完成的:

tspec := hcldec.ObjectSpec{
    "target": &hcldec.BlockMapSpec{
        TypeName:   "target",
        LabelNames: []string{"table"},
        Nested: hcldec.ObjectSpec{
            "cols": &hcldec.BlockMapSpec{
                TypeName:   "cols",
                LabelNames: []string{"name"},
                Nested: &hcldec.ObjectSpec{
                    "name": &hcldec.AttrSpec{
                        Name:     "name",
                        Type:     cty.String, //cty.List(cty.String),
                        Required: false,
                    },
                    "type": &hcldec.AttrSpec{
                        Name:     "type",
                        Type:     cty.String, //cty.List(cty.String),
                        Required: false,
                    },
                    "length": &hcldec.AttrSpec{
                        Name:     "length",
                        Type:     cty.String, //cty.List(cty.String),
                        Required: false,
                    },
                },
            },
        },
    },
}


targ, _ := hcldec.Decode(body, tspec, &hcl.EvalContext{
    Variables: map[string]cty.Value{
        "source": val.GetAttr("source"),
    },
    Functions: nil,
})

j := decodeCtyToJson(targ, true)
log.Debugf("targ -j (spec): %s", string(j))    // debug info

decodeCtyToJson 像这样返回 []byte 的地方:

func decodeCtyToJson(value cty.Value, pretty bool) []byte {
    jsonified, err := ctyjson.Marshal(value, cty.DynamicPseudoType)
    if err != nil {
        log.Debugf("Error: #v", err)
        return nil
    }
    if pretty {
        return jsonPretty.Pretty(jsonified)
    }
    return jsonified
}

现在,当我尝试测试打印 JSON 内容时,我没有得到我正在寻找的内容:

var result map[string]interface{}
json.Unmarshal(j, &result)
log.Debugf("result: %# v", result)

tgtfil := result["value"].(map[string]interface{})
log.Debugf("tgtfil: %v", tgtfil)

log.Debugf("len(tgtfil): %# v", len(tgtfil))
for key, value := range tgtfil {
    log.Debugf("key: %# v", key)
    log.Debugf("value: %# v", value)
}

我正在尝试获取键值对。但是我得到了这个(首先是整个 JSON 的漂亮打印,然后我试图遍历 JSON):

DEBU[0000] targ -j (spec): {
  "value": {
    "target": {
      "table": {
        "cols": {
          "firstName": {
            "length": "30",
            "name": "$.firstName",
            "type": "varchar"
          },
          "lastName": {
            "length": "40",
            "name": "$.lastName",
            "type": "varchar"
          }
        }
      }
    }
  },
  "type": [
    "object", 
    {
      "target": [
        "map", 
        [
          "object", 
          {
            "cols": [
              "map", 
              [
                "object", 
                {
                  "length": "string",
                  "name": "string",
                  "type": "string"
                }
              ]
            ]
          }
        ]
      ]
    }
  ]
} 
DEBU[0000] result: map[string]interface {}{"type":[]interface {}{"object", map[string]interface {}{"target":[]interface {}{"map", []interface {}{"object", map[string]interface {}{"cols":[]interface {}{"map", []interface {}{"object", map[string]interface {}{"length":"string", "name":"string", "type":"string"}}}}}}}}, "value":map[string]interface {}{"target":map[string]interface {}{"table":map[string]interface {}{"cols":map[string]interface {}{"firstName":map[string]interface {}{"length":"30", "name":"$.firstName", "type":"varchar"}, "lastName":map[string]interface {}{"length":"40", "name":"$.lastName", "type":"varchar"}}}}}} 
DEBU[0000] tgtfil: map[target:map[table:map[cols:map[firstName:map[length:30 name:$.firstName type:varchar] lastName:map[length:40 name:$.lastName type:varchar]]]]] 
DEBU[0000] len(tgtfil):  1                              
DEBU[0000] key: "target"                                
DEBU[0000] value: map[string]interface {}{"table":map[string]interface {}{"cols":map[string]interface {}{"firstName":map[string]interface {}{"length":"30", "name":"$.firstName", "type":"varchar"}, "lastName":map[string]interface {}{"length":"40", "name":"$.lastName", "type":"varchar"}}}} 

Process finished with exit code 0

我的目标是最终能够遍历 target.hcl 中定义的所有属性(在这种情况下,每个 cols 的长度、名称和类型)。然后根据这些信息生成 DDL 代码,最后在 Presto 中实现 DDL。

但截至目前,我无法隔离这些信息。

任何有关如何执行此操作的指示都值得赞赏。

谢谢,/b

4

1 回答 1

0

我的解决方案是为目标创建一个结构而不使用目标规范。

于 2020-05-05T07:42:19.897 回答