hcl, json, go: как я могу повторить JSON? - PullRequest
0 голосов
/ 29 апреля 2020

Проблема: я пытаюсь перебрать содержание JSON и представить результат в виде пар ключ-значение.

Я написал некоторый код, который читает hcl-файлы, затем они декодируются с помощью hclde c .Decode, и результат затем преобразуется в JSON. Эти hcl-файлы определяют источник и цель для приложения следующим образом:

source.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"
  }
}

target.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

Где decodeCtyTo Json возвращает байт [] так:

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 -контента I ' я не получаю то, что ищу:

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 симпатичную распечатку, как хотелось, затем я пытаюсь пройти oop через 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 (длина, имя и тип для каждого col в этом случае). Затем сгенерируйте DDL-код из этой информации и, наконец, внедрите DDL, например, в Presto.

Но на данный момент я не могу выделить эту информацию.

Любые указатели о том, как это сделать ценится.

Спасибо, / b

1 Ответ

0 голосов
/ 05 мая 2020

Решением для меня было создать структуру для цели, а не использовать целевую спецификацию c.

...