Итерация по карте, декодированной из формата PHP-сериализации - PullRequest
0 голосов
/ 27 сентября 2018

Как я могу прочитать условия не сериализованные данные в формате golang в формате карты?

[map[19:map[conditions:map[0:map[operator:== value:AMW-1900-50SLE-ROOM 
is_value_processed:false type:feedexport/rule_condition_product 
attribute:sku] 1:map[type:feedexport/rule_condition_product 
attribute:sku operator:== value:ASL-B654-77-74-98-ROOM 
is_value_processed:false] 2:map[is_value_processed:false 
type:feedexport/rule_condition_product attribute:sku operator:== 
value:ASL-B217-57-54S-95-ROOM]] type:feedexport/rule_condition_combine 
attribute:<nil> operator:<nil> value:1 is_value_processed:<nil> 
aggregator:any]]]

Это код:

package main

import (
    "fmt"
    "github.com/wulijun/go-php-serialize/phpserialize"
)

func main() {
    rules := RulesList()
    for _, rule := range rules{
        fmt.Println(rule.Conditions.(interface{}))
    }
}

type Rule struct {
    RuleId     int         `json:"rule_id"`
    Conditions interface{} `json:"conditions"`
}

func RulesList() ([]Rule) {
    db := DbConn()
    res, err := db.Query(`SELECT r.rule_id, r.conditions_serialized AS 
    conditions FROM m_feedexport_rule AS r`)
    CheckError(err)
    rule  := Rule{}
    rules := []Rule{}
    for res.Next()  {
        var ruleId int
        var conditions string
        err = res.Scan(&ruleId, &conditions)
        CheckError(err)
        cons, err := phpserialize.Decode(conditions)
        CheckError(err)
        rule.RuleId     = ruleId
        rule.Conditions = cons   
        rules = append(rules, rule)
    }
    return rules
}

Результат в порядке, но мне нужно это в форме карты, теперь это интерфейс, который я не могу зациклить. В случае, если кто-то не понимает код, спросите меня.Большое спасибо.

1 Ответ

0 голосов
/ 27 сентября 2018

Вы говорите о типе переменной cons, не так ли?

Фон

Если да, причина его типа interface{} в том, что в PHP этовозможно сериализовать значение любого типа (от простого целого до сложного объекта), и, следовательно, любой код десериализации должен справиться с этим.Так как в Go так называемый «пустой интерфейс», interface{}, удовлетворяется любым типом вообще (включая любой пользовательский тип, реализованный программистом), очень важно, чтобы декодер сериализованных данных PHP возвращал значение типаinterface{}.

Решение

Убедившись, что декодирование прошло успешно, вам нужно либо type-assert получить результирующее значение нужного вам типа, либо использовать переключатель типа для отклонения обработки на основе конкретного типа значения, возвращаемого декодером.

Подход очень хорошо продемонстрирован пакетом, который вы используете в своем собственном наборе тестов .

Фрагмент, демонстрирующий основной подход

if decodeRes, err = Decode(result); err != nil {
    t.Errorf("decode data fail %v, %v", err, result)
    return
}
decodeData, ok := decodeRes.(map[interface{}]interface{})
if !ok {
    t.Errorf("decode data type error, expected: map[interface{}]interface{}, get: %T", decodeRes)
    return
}
obj, _ := decodeData["object"].(*PhpObject)
if v, _ := obj.GetPrivateMemberValue("a"); v != int64(1) {
    t.Errorf("object private value expected 1, get %v, %T", v, v)
}
if v := obj.GetClassName(); v != "A" {
    t.Errorf("object class name expected A, get %v", v)
}

Здесь decodeRes - это то, что возвращается декодером.Это значение затем утверждается типом, чтобы убедиться, что его конкретный тип (также называемый «динамический», то есть «во время выполнения») равен map[interface{}]interface{}.

Обратите внимание, что так называемый «два аргумента»«Используется тип assert (также называемый« идиома запятой »), чтобы не вызывать панику программы во время выполнения, если конкретный тип отличается от ожидаемого (всегда делайте это с данными, извлекаемыми извне!).

Значение установленного типа конкретного типа сохраняется в переменной decodeData, а затем эта переменная проверяется далее.

...