safe_loadを使用してPyYAMLとしたオブジェクトを逆シリアル化するには?

StackOverflow https://stackoverflow.com/questions/2627555

  •  26-09-2019
  •  | 
  •  

質問

このようなスニペットを持ちます

import yaml
class User(object):
    def __init__(self, name, surname):
       self.name= name
       self.surname= surname

user = User('spam', 'eggs')
serialized_user = yaml.dump(user)
#Network
deserialized_user = yaml.load(serialized_user)
print "name: %s, sname: %s" % (deserialized_user.name, deserialized_user.surname)

YAMLドキュメントを呼び出すことは安全ではないことを言います>信頼できないソースから受信したデータと、使用するので、私は私のスニペットに何を変更する必要があります\クラスの safe_load の方法?
それは可能でしょうか?

役に立ちましたか?

解決

これは、定義によって、そのsafe_loadを表示され、あなたがあなた自身のクラスをデシリアライズできません。あなたはそれが安全になりたい場合は、私はこのような何かをしたい:

import yaml
class User(object):
    def __init__(self, name, surname):
       self.name= name
       self.surname= surname

    def yaml(self):
       return yaml.dump(self.__dict__)

    @staticmethod
    def load(data):
       values = yaml.safe_load(data)
       return User(values["name"], values["surname"])

user = User('spam', 'eggs')
serialized_user = user.yaml()
print "serialized_user:  %s" % serialized_user.strip()

#Network
deserialized_user = User.load(serialized_user)
print "name: %s, sname: %s" % (deserialized_user.name, deserialized_user.surname)
ここでの利点は、あなたがあなたのクラスがどのようにオーバー絶対コントロール(デ)シリアライズを持っているということです。あなたがネットワーク上でランダムな実行可能コードを取得し、それを実行しないであろうことを意味します。欠点は、あなたがあなたのクラスがどのようにオーバー絶対コントロール(デ)シリアライズを持っているということです。手段は、あなたがより多くの仕事をしなければならないこと。 ; - )

他のヒント

もう一つの方法は存在します。 PyYAMLとドキュメントから:

  

Pythonオブジェクトは安全なので、yaml.safe_loadによって認識されるようにマークすることができます。これを行うには、[...] yaml.YAMLObjectからそれを導出し、明示的yaml.SafeLoaderにそのクラスのプロパティyaml_loaderを設定します。

あなたもそれを動作させるためにyaml_tagプロパティを設定する必要があります。

YAMLObjectは、オブジェクトのロード可能にするためにいくつかのメタクラスの魔法を行います。あなたがこれを行う場合、オブジェクトのみ)(ではない通常のyaml.loadで、安全なローダによってロード可能になることに注意してください。

作業例:

import yaml

class User(yaml.YAMLObject):
    yaml_loader = yaml.SafeLoader
    yaml_tag = u'!User'

    def __init__(self, name, surname):
       self.name= name
       self.surname= surname

user = User('spam', 'eggs')
serialized_user = yaml.dump(user)

#Network

deserialized_user = yaml.safe_load(serialized_user)
print "name: %s, sname: %s" % (deserialized_user.name, deserialized_user.surname)

この1の利点は、それを行うのは簡単pretyだということです。欠点は、それが唯一のsafe_loadとクラッタシリアライズ関連の属性とメタクラスであなたのクラスで動作するということです。

あなたは多くのタグを持っており、それらのすべてのためのオブジェクトを作成したくない、あるいは場合には、あなたが実際の型のみが点線のアクセスについては、返却を気にしない場合は、次のコードですべての未定義のタグをキャッチ:

import yaml

class Blob(object):
    def update(self, kw):
        for k in kw:
            setattr(self, k, kw[k])

from yaml.constructor import SafeConstructor

def my_construct_undefined(self, node):
    data = Blob()
    yield data
    value = self.construct_mapping(node)
    data.update(value)

SafeConstructor.add_constructor(None, my_construct_undefined)


class User(object):
    def __init__(self, name, surname):
        self.name= name
        self.surname= surname

user = User('spam', 'eggs')
serialized_user = yaml.dump(user)
#Network
deserialized_user = yaml.safe_load(serialized_user)
print "name: %s, sname: %s" % (deserialized_user.name, deserialized_user.surname)

my_construct_undefinedが真ん中にyieldているなぜあなたは不思議場合:その子の作成とは別にオブジェクトをインスタンス化することができます。オブジェクト一度アンカーを有し、子供(または彼らの子供)参照、それは場合に参照することができる存在します。オブジェクトを作成するために、実際のmechanismeが最初にそれを作成し、それを最終決定することにnext(x)を行います。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top