@classmethod<EOL><INDENT>def deserialize(cls, value):<DEDENT>
if getattr(value, "<STR_LIT>", None):<EOL><INDENT>value = value.decode()<EOL><DEDENT>logger.debug("<STR_LIT>", value)<EOL>parsed = json.loads(value)<EOL>if "<STR_LIT:port>" not in parsed:<EOL><INDENT>raise ValueError("<STR_LIT>")<EOL><DEDENT>if "<STR_LIT>" not in parsed:<EOL><INDENT>raise ValueError("<STR_LIT>")<EOL><DEDENT>if "<STR_LIT:host>" not in parsed:<EOL><INDENT>host, aliases, ip_list = socket.gethostbyaddr(parsed["<STR_LIT>"])<EOL>parsed["<STR_LIT:host>"] = socket.get_fqdn(host)<EOL><DEDENT>if "<STR_LIT>" in parsed:<EOL><INDENT>peer = Peer.deserialize(parsed["<STR_LIT>"])<EOL><DEDENT>else:<EOL><INDENT>peer = None<EOL><DEDENT>return cls(<EOL>parsed["<STR_LIT:host>"], parsed["<STR_LIT>"], parsed["<STR_LIT:port>"],<EOL>peer=peer, metadata=parsed.get("<STR_LIT>")<EOL>)<EOL>
Creates a new Node instance via a JSON map string.

Note that `port` and `ip` and are required keys for the JSON map,
`peer` and `host` are optional.  If `peer` is not present, the new Node
instance will use the current peer.  If `host` is not present, the
hostname of the given `ip` is looked up.