Repository: bigchaindb/cryptoconditions

Issue:
Remove json serialization from cryptoconditions
Just provide functions for serialization to dicts.
Users should be able to serialize from there on to dicts themselves.

Discussion:

Patch:
diff --git a/README.md b/README.md
index 4387e6e..6c963c8 100644
--- a/README.md
+++ b/README.md
@@ -39,6 +39,7 @@ generic authenticated event handlers.
 ## Usage
 
 ```python
+import json
 import binascii
 import cryptoconditions as cc
 
@@ -64,7 +65,7 @@ parsed_fulfillment = cc.Fulfillment.from_uri(example_fulfillment_uri)
 print(isinstance(parsed_fulfillment, cc.PreimageSha256Fulfillment))
 # prints True
 
-# Retrieve the condition of the fulfillment 
+# Retrieve the condition of the fulfillment
 print(parsed_fulfillment.condition_uri)
 # prints 'cc:0:3:47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU:0'
 
@@ -72,14 +73,13 @@ print(parsed_fulfillment.condition_uri)
 parsed_fulfillment.validate()
 # prints True
 
-# Export to JSON
-json_data = parsed_fulfillment.serialize_json()
+# Serialize fulfillment to JSON
+json_data = json.dumps(parsed_fulfillment.to_dict())
 print(json_data)
 # prints '{"bitmask": 3, "type_id": 0, "type": "fulfillment", "preimage": ""}'
 
 # Parse fulfillment from JSON
-import json
-json_fulfillment = cc.Fulfillment.from_json(json.loads(json_data))
+json_fulfillment = cc.Fulfillment.from_dict(json.loads(json_data))
 print(json_fulfillment.serialize_uri())
 # prints 'cf:0:'
 ```
@@ -270,6 +270,7 @@ FULFILLMENT_PAYLOAD =
 ### Usage
 
 ```python
+import json
 import cryptoconditions as cc
 
 # Parse some fulfillments
@@ -315,7 +316,7 @@ threshold_fulfillment.threshold = 3 # AND gate
 
 print(threshold_fulfillment.serialize_uri())
 # prints 'cf:2:AQMBAwEBAwAAAAABAWMABGDsFyuTrV5WO_STLHDhJFA0w1Rn7y79TWTr-BloNGfiv7YikfrZQy-PKYucSkiV2-KT9v_aGmja3wzN719HoMchKl_qPNqXo_TAPqny6Kwc7IalHUUhJ6vboJ0bbzMcBwoAAQGBmgACgZYBAQECAQEAJwAEASAg7Bcrk61eVjv0kyxw4SRQNMNUZ-8u_U1k6_gZaDRn4r8BYAEBYwAEYOwXK5OtXlY79JMscOEkUDTDVGfvLv1NZOv4GWg0Z-K_tiKR-tlDL48pi5xKSJXb4pP2_9oaaNrfDM3vX0egxyEqX-o82pej9MA-qfLorBzshqUdRSEnq9ugnRtvMxwHCgAA'
-threshold_fulfillment.serialize_json()
+threshold_fulfillment.to_dict()
 ```
 
 ```python
@@ -416,4 +417,4 @@ timeout_fulfillment valid: False (0s to timeout)
 timeout_fulfillment valid: False (-1s to timeout)
 timeout_fulfillment valid: False (-2s to timeout)
 timeout_fulfillment valid: False (-3s to timeout)
-```
\ No newline at end of file
+```
diff --git a/cryptoconditions/condition.py b/cryptoconditions/condition.py
index 4ae9d75..d00427a 100644
--- a/cryptoconditions/condition.py
+++ b/cryptoconditions/condition.py
@@ -1,4 +1,3 @@
-import json
 import base58
 import base64
 import re
@@ -117,18 +116,18 @@ class Condition(metaclass=ABCMeta):
         return condition
 
     @staticmethod
-    def from_json(json_data):
+    def from_dict(data):
         """
-        Create a Condition object from a json dict.
+        Create a Condition object from a dict.
 
         Args:
-            json_data (dict): Dictionary containing the condition payload
+            data (dict): Dictionary containing the condition payload
 
         Returns:
             Condition: Resulting object
         """
         condition = Condition()
-        condition.parse_json(json_data)
+        condition.parse_dict(data)
 
         return condition
 
@@ -262,30 +261,34 @@ class Condition(metaclass=ABCMeta):
         self.hash = reader.read_var_octet_string()
         self.max_fulfillment_length = reader.read_var_uint()
 
-    def serialize_json(self):
-        return json.dumps(
-            {
-                'type': 'condition',
-                'type_id': self.type_id,
-                'bitmask': self.bitmask,
-                'hash': base58.b58encode(self.hash),
-                'max_fulfillment_length': self.max_fulfillment_length
-            }
-        )
+    def to_dict(self):
+        """
+        Generate a dict of the condition
 
-    def parse_json(self, json_data):
+        Returns:
+            dict: representing the condition
+        """
+        return {
+            'type': 'condition',
+            'type_id': self.type_id,
+            'bitmask': self.bitmask,
+            'hash': base58.b58encode(self.hash),
+            'max_fulfillment_length': self.max_fulfillment_length
+        }
+
+    def parse_dict(self, data):
         """
 
         Args:
-            json_data (dict):
+            data (dict):
         Returns:
             Condition with payload
         """
-        self.type_id = json_data['type_id']
-        self.bitmask = json_data['bitmask']
+        self.type_id = data['type_id']
+        self.bitmask = data['bitmask']
 
-        self.hash = base58.b58decode(json_data['hash'])
-        self.max_fulfillment_length = json_data['max_fulfillment_length']
+        self.hash = base58.b58decode(data['hash'])
+        self.max_fulfillment_length = data['max_fulfillment_length']
 
     def validate(self):
         """
diff --git a/cryptoconditions/fulfillment.py b/cryptoconditions/fulfillment.py
index c07a281..f78e5af 100644
--- a/cryptoconditions/fulfillment.py
+++ b/cryptoconditions/fulfillment.py
@@ -78,12 +78,12 @@ class Fulfillment(metaclass=ABCMeta):
         return fulfillment
 
     @staticmethod
-    def from_json(json_data):
-        cls_type = json_data['type_id']
+    def from_dict(data):
+        cls_type = data['type_id']
         cls = TypeRegistry.get_class_from_type_id(cls_type)
 
         fulfillment = cls()
-        fulfillment.parse_json(json_data)
+        fulfillment.parse_dict(data)
 
         return fulfillment
 
@@ -249,20 +249,20 @@ class Fulfillment(metaclass=ABCMeta):
         """
 
     @abstractmethod
-    def serialize_json(self):
+    def to_dict(self):
         """
-        Generate a JSON object of the fulfillment
+        Generate a dict of the fulfillment
 
         Returns:
         """
 
     @abstractmethod
-    def parse_json(self, json_data):
+    def parse_dict(self, data):
         """
-        Generate fulfillment payload from a json
+        Generate fulfillment payload from a dict
 
         Args:
-            json_data: json description of the fulfillment
+            data: dict description of the fulfillment
 
         Returns:
             Fulfillment
diff --git a/cryptoconditions/types/ed25519.py b/cryptoconditions/types/ed25519.py
index fb8fd32..ddcf8fa 100644
--- a/cryptoconditions/types/ed25519.py
+++ b/cryptoconditions/types/ed25519.py
@@ -1,5 +1,3 @@
-import json
-
 import base58
 
 from cryptoconditions.crypto import Ed25519VerifyingKey as VerifyingKey
@@ -113,34 +111,33 @@ class Ed25519Fulfillment(Fulfillment):
     def calculate_max_fulfillment_length(self):
         return Ed25519Fulfillment.FULFILLMENT_LENGTH
 
-    def serialize_json(self):
+    def to_dict(self):
         """
-        Generate a JSON object of the fulfillment
+        Generate a dict of the fulfillment
 
         Returns:
+            dict: representing the fulfillment
         """
-        return json.dumps(
-            {
-                'type': 'fulfillment',
-                'type_id': self.TYPE_ID,
-                'bitmask': self.bitmask,
-                'public_key': self.public_key.to_ascii(encoding='base58').decode(),
-                'signature': base58.b58encode(self.signature) if self.signature else None
-            }
-        )
+        return {
+            'type': 'fulfillment',
+            'type_id': self.TYPE_ID,
+            'bitmask': self.bitmask,
+            'public_key': self.public_key.to_ascii(encoding='base58').decode(),
+            'signature': base58.b58encode(self.signature) if self.signature else None
+        }
 
-    def parse_json(self, json_data):
+    def parse_dict(self, data):
         """
-        Generate fulfillment payload from a json
+        Generate fulfillment payload from a dict
 
         Args:
-            json_data: json description of the fulfillment
+            data (dict): description of the fulfillment
 
         Returns:
             Fulfillment
         """
-        self.public_key = VerifyingKey(json_data['public_key'])
-        self.signature = base58.b58decode(json_data['signature']) if json_data['signature'] else None
+        self.public_key = VerifyingKey(data['public_key'])
+        self.signature = base58.b58decode(data['signature']) if data['signature'] else None
 
     def validate(self, message=None, **kwargs):
         """
diff --git a/cryptoconditions/types/sha256.py b/cryptoconditions/types/sha256.py
index daa2e00..f36e96a 100644
--- a/cryptoconditions/types/sha256.py
+++ b/cryptoconditions/types/sha256.py
@@ -1,5 +1,3 @@
-import json
-
 from cryptoconditions.types.base_sha256 import BaseSha256Fulfillment
 from cryptoconditions.lib import Hasher, Reader, Writer, Predictor
 
@@ -93,32 +91,31 @@ class PreimageSha256Fulfillment(BaseSha256Fulfillment):
         writer.write(self.preimage)
         return writer
 
-    def serialize_json(self):
+    def to_dict(self):
         """
-        Generate a JSON object of the fulfillment
+        Generate a dict of the fulfillment
 
         Returns:
+            dict: representing the fulfillment
         """
-        return json.dumps(
-            {
-                'type': 'fulfillment',
-                'type_id': self.TYPE_ID,
-                'bitmask': self.bitmask,
-                'preimage': self.preimage.decode()
-            }
-        )
-
-    def parse_json(self, json_data):
+        return {
+            'type': 'fulfillment',
+            'type_id': self.TYPE_ID,
+            'bitmask': self.bitmask,
+            'preimage': self.preimage.decode()
+        }
+
+    def parse_dict(self, data):
         """
-        Generate fulfillment payload from a json
+        Generate fulfillment payload from a dict
 
         Args:
-            json_data: json description of the fulfillment
+            data (dict): description of the fulfillment
 
         Returns:
             Fulfillment
         """
-        self.preimage = json_data['preimage'].encode()
+        self.preimage = data['preimage'].encode()
 
     def validate(self, *args, **kwargs):
         """
diff --git a/cryptoconditions/types/threshold_sha256.py b/cryptoconditions/types/threshold_sha256.py
index 068e9b2..aae4e02 100644
--- a/cryptoconditions/types/threshold_sha256.py
+++ b/cryptoconditions/types/threshold_sha256.py
@@ -1,5 +1,3 @@
-import json
-
 import copy
 from cryptoconditions.condition import Condition
 from cryptoconditions.fulfillment import Fulfillment
@@ -109,6 +107,7 @@ class ThresholdSha256Fulfillment(BaseSha256Fulfillment):
         elif not isinstance(subfulfillment, Fulfillment):
             raise TypeError('Subfulfillments must be URIs or objects of type Fulfillment')
         if not isinstance(weight, int) or weight < 1:
+            # TODO: Add a more helpful error message.
             raise ValueError('Invalid weight: {}'.format(weight))
         self.subconditions.append(
             {
@@ -277,7 +276,7 @@ class ThresholdSha256Fulfillment(BaseSha256Fulfillment):
 
         predictor = Predictor()
         predictor.write_uint16(None)                       # type
-        predictor.write_var_octet_string(b'0'*fulfillment_len)  # payload
+        predictor.write_var_octet_string(b'0' * fulfillment_len)  # payload
 
         return predictor.size
 
@@ -486,49 +485,48 @@ class ThresholdSha256Fulfillment(BaseSha256Fulfillment):
         buffers_copy.sort(key=lambda item: (len(item), item))
         return buffers_copy
 
-    def serialize_json(self):
+    def to_dict(self):
         """
-        Generate a JSON object of the fulfillment
+        Generate a dict of the fulfillment
 
         Returns:
+            dict: representing the fulfillment
         """
-        subfulfillments_json = []
+        subfulfillments = []
         for c in self.subconditions:
-            subcondition = json.loads(c['body'].serialize_json())
+            subcondition = c['body'].to_dict()
             subcondition.update({'weight': c['weight']})
-            subfulfillments_json.append(subcondition)
+            subfulfillments.append(subcondition)
 
-        return json.dumps(
-            {
-                'type': 'fulfillment',
-                'type_id': self.TYPE_ID,
-                'bitmask': self.bitmask,
-                'threshold': self.threshold,
-                'subfulfillments': subfulfillments_json
-            }
-        )
+        return {
+            'type': 'fulfillment',
+            'type_id': self.TYPE_ID,
+            'bitmask': self.bitmask,
+            'threshold': self.threshold,
+            'subfulfillments': subfulfillments
+        }
 
-    def parse_json(self, json_data):
+    def parse_dict(self, data):
         """
-        Generate fulfillment payload from a json
+        Generate fulfillment payload from a dict
 
         Args:
-            json_data: json description of the fulfillment
+            data (dict): description of the fulfillment
 
         Returns:
             Fulfillment
         """
-        if not isinstance(json_data, dict):
+        if not isinstance(data, dict):
             raise TypeError('reader must be a dict instance')
-        self.threshold = json_data['threshold']
+        self.threshold = data['threshold']
 
-        for subfulfillments_json in json_data['subfulfillments']:
-            weight = subfulfillments_json['weight']
+        for subfulfillments in data['subfulfillments']:
+            weight = subfulfillments['weight']
 
-            if subfulfillments_json['type'] == FULFILLMENT:
-                self.add_subfulfillment(Fulfillment.from_json(subfulfillments_json), weight)
-            elif subfulfillments_json['type'] == CONDITION:
-                self.add_subcondition(Condition.from_json(subfulfillments_json), weight)
+            if subfulfillments['type'] == FULFILLMENT:
+                self.add_subfulfillment(Fulfillment.from_dict(subfulfillments), weight)
+            elif subfulfillments['type'] == CONDITION:
+                self.add_subcondition(Condition.from_dict(subfulfillments), weight)
             else:
                 raise TypeError('Subconditions must provide either subcondition or fulfillment.')
 
diff --git a/cryptoconditions/types/timeout.py b/cryptoconditions/types/timeout.py
index 6b9d2fc..0007c6f 100644
--- a/cryptoconditions/types/timeout.py
+++ b/cryptoconditions/types/timeout.py
@@ -1,4 +1,3 @@
-import json
 import re
 import time
 
@@ -32,32 +31,31 @@ class TimeoutFulfillment(PreimageSha256Fulfillment):
         """
         return self.preimage
 
-    def serialize_json(self):
+    def to_dict(self):
         """
-        Generate a JSON object of the fulfillment
+        Generate a dict of the fulfillment
 
         Returns:
+            dict: representing the fulfillment
         """
-        return json.dumps(
-            {
-                'type': 'fulfillment',
-                'type_id': self.TYPE_ID,
-                'bitmask': self.bitmask,
-                'expire_time': self.expire_time.decode()
-            }
-        )
-
-    def parse_json(self, json_data):
+        return {
+            'type': 'fulfillment',
+            'type_id': self.TYPE_ID,
+            'bitmask': self.bitmask,
+            'expire_time': self.expire_time.decode()
+        }
+
+    def parse_dict(self, data):
         """
-        Generate fulfillment payload from a json
+        Generate fulfillment payload from a dict
 
         Args:
-            json_data: json description of the fulfillment
+            data (dict): description of the fulfillment
 
         Returns:
             Fulfillment
         """
-        self.preimage = json_data['expire_time'].encode()
+        self.preimage = data['expire_time'].encode()
 
     def validate(self, message=None, now=None, **kwargs):
         """
diff --git a/setup.py b/setup.py
index c467ce2..d4da1b4 100644
--- a/setup.py
+++ b/setup.py
@@ -69,8 +69,7 @@ setup(
     tests_require=tests_require,
     extras_require={
         'test': tests_require,
-        'dev':  dev_require + tests_require + docs_require,
-        'docs':  docs_require,
+        'dev': dev_require + tests_require + docs_require,
+        'docs': docs_require,
     },
 )
-


Test patch:
diff --git a/tests/test_fulfillment.py b/tests/test_fulfillment.py
index 225c85c..10d75dc 100644
--- a/tests/test_fulfillment.py
+++ b/tests/test_fulfillment.py
@@ -1,5 +1,4 @@
 import binascii
-import json
 from time import sleep
 
 from math import ceil
@@ -45,20 +44,13 @@ class TestSha256Fulfillment:
         assert fulfillment.condition.serialize_uri() == fulfillment_sha256['condition_uri']
         assert fulfillment.validate()
 
-    def test_serialize_json(self, fulfillment_sha256):
+    def test_fulfillment_serialize_to_dict(self, fulfillment_sha256):
         fulfillment = Fulfillment.from_uri(fulfillment_sha256['fulfillment_uri'])
-
-        assert json.loads(fulfillment.serialize_json()) == \
-            {'bitmask': 3, 'preimage': '', 'type': 'fulfillment', 'type_id': 0}
-
-    def test_deserialize_json(self, fulfillment_sha256):
-        fulfillment = Fulfillment.from_uri(fulfillment_sha256['fulfillment_uri'])
-        fulfillment_json = json.loads(fulfillment.serialize_json())
-        parsed_fulfillment = fulfillment.from_json(fulfillment_json)
+        parsed_fulfillment = fulfillment.from_dict(fulfillment.to_dict())
 
         assert parsed_fulfillment.serialize_uri() == fulfillment.serialize_uri()
         assert parsed_fulfillment.condition.serialize_uri() == fulfillment.condition.serialize_uri()
-        assert parsed_fulfillment.serialize_json() == fulfillment.serialize_json()
+        assert parsed_fulfillment.to_dict() == fulfillment.to_dict()
 
     def test_deserialize_condition_and_validate_fulfillment(self, fulfillment_sha256):
         condition = Condition.from_uri(fulfillment_sha256['condition_uri'])
@@ -123,10 +115,10 @@ class TestEd25519Sha256Fulfillment:
         assert deserialized_condition.serialize_uri() == fulfillment_ed25519['condition_uri']
         assert binascii.hexlify(deserialized_condition.hash) == fulfillment_ed25519['condition_hash']
 
-    def test_serialize_json_signed(self, fulfillment_ed25519):
+    def test_serialize_signed_dict_to_fulfillment(self, fulfillment_ed25519):
         fulfillment = Fulfillment.from_uri(fulfillment_ed25519['fulfillment_uri'])
 
-        assert json.loads(fulfillment.serialize_json()) == \
+        assert fulfillment.to_dict()== \
             {'bitmask': 32,
              'public_key': 'Gtbi6WQDB6wUePiZm8aYs5XZ5pUqx9jMMLvRVHPESTjU',
              'signature': '4eCt6SFPCzLQSAoQGW7CTu3MHdLj6FezSpjktE7tHsYGJ4pNSUnpHtV9XgdHF2XYd62M9fTJ4WYdhTVck27qNoHj',
@@ -135,10 +127,10 @@ class TestEd25519Sha256Fulfillment:
 
         assert fulfillment.validate(MESSAGE) == True
 
-    def test_serialize_json_unsigned(self, vk_ilp):
+    def test_serialize_unsigned_dict_to_fulfillment(self, vk_ilp):
         fulfillment = Ed25519Fulfillment(public_key=vk_ilp['b58'])
 
-        assert json.loads(fulfillment.serialize_json()) == \
+        assert fulfillment.to_dict() == \
             {'bitmask': 32,
              'public_key': 'Gtbi6WQDB6wUePiZm8aYs5XZ5pUqx9jMMLvRVHPESTjU',
              'signature': None,
@@ -146,23 +138,20 @@ class TestEd25519Sha256Fulfillment:
              'type_id': 4}
         assert fulfillment.validate(MESSAGE) == False
 
-    def test_deserialize_json_signed(self, fulfillment_ed25519):
+    def test_deserialize_signed_dict_to_fulfillment(self, fulfillment_ed25519):
         fulfillment = Fulfillment.from_uri(fulfillment_ed25519['fulfillment_uri'])
-        fulfillment_json = json.loads(fulfillment.serialize_json())
-        parsed_fulfillment = fulfillment.from_json(fulfillment_json)
+        parsed_fulfillment = fulfillment.from_dict(fulfillment.to_dict())
 
         assert parsed_fulfillment.serialize_uri() == fulfillment_ed25519['fulfillment_uri']
         assert parsed_fulfillment.condition.serialize_uri() == fulfillment.condition.serialize_uri()
-        assert parsed_fulfillment.serialize_json() == fulfillment.serialize_json()
+        assert parsed_fulfillment.to_dict() == fulfillment.to_dict()
 
-    def test_deserialize_json_unsigned(self, vk_ilp):
+    def test_deserialize_unsigned_dict_to_fulfillment(self, vk_ilp):
         fulfillment = Ed25519Fulfillment(public_key=vk_ilp['b58'])
-
-        fulfillment_json = json.loads(fulfillment.serialize_json())
-        parsed_fulfillment = fulfillment.from_json(fulfillment_json)
+        parsed_fulfillment = fulfillment.from_dict(fulfillment.to_dict())
 
         assert parsed_fulfillment.condition.serialize_uri() == fulfillment.condition.serialize_uri()
-        assert parsed_fulfillment.serialize_json() == fulfillment.serialize_json()
+        assert parsed_fulfillment.to_dict() == fulfillment.to_dict()
 
     def test_serialize_deserialize_condition(self, vk_ilp):
         vk = VerifyingKey(vk_ilp['b58'])
@@ -262,10 +251,10 @@ class TestThresholdSha256Fulfillment:
         assert len(fulfillment.subconditions) == num_fulfillments
         assert fulfillment.validate(MESSAGE)
 
-    def test_serialize_json_signed(self, fulfillment_threshold):
+    def test_serialize_signed_dict_to_fulfillment(self, fulfillment_threshold):
         fulfillment = Fulfillment.from_uri(fulfillment_threshold['fulfillment_uri'])
 
-        assert json.loads(fulfillment.serialize_json()) == \
+        assert fulfillment.to_dict() == \
             {'bitmask': 43,
              'subfulfillments': [{'bitmask': 3,
                                   'preimage': '',
@@ -282,12 +271,12 @@ class TestThresholdSha256Fulfillment:
              'type': 'fulfillment',
              'type_id': 2}
 
-    def test_serialize_json_unsigned(self, vk_ilp):
+    def test_serialize_unsigned_dict_to_fulfillment(self, vk_ilp):
         fulfillment = ThresholdSha256Fulfillment(threshold=1)
         fulfillment.add_subfulfillment(Ed25519Fulfillment(public_key=VerifyingKey(vk_ilp['b58'])))
         fulfillment.add_subfulfillment(Ed25519Fulfillment(public_key=VerifyingKey(vk_ilp['b58'])))
 
-        assert json.loads(fulfillment.serialize_json()) == \
+        assert fulfillment.to_dict() == \
             {'bitmask': 41,
              'subfulfillments': [{'bitmask': 32,
                                   'public_key': 'Gtbi6WQDB6wUePiZm8aYs5XZ5pUqx9jMMLvRVHPESTjU',
@@ -305,50 +294,45 @@ class TestThresholdSha256Fulfillment:
              'type': 'fulfillment',
              'type_id': 2}
 
-    def test_deserialize_json_signed(self, fulfillment_threshold):
+    def test_deserialize_signed_dict_to_fulfillment(self, fulfillment_threshold):
         fulfillment = Fulfillment.from_uri(fulfillment_threshold['fulfillment_uri'])
-        fulfillment_json = json.loads(fulfillment.serialize_json())
-        parsed_fulfillment = fulfillment.from_json(fulfillment_json)
+        parsed_fulfillment = fulfillment.from_dict(fulfillment.to_dict())
 
         assert parsed_fulfillment.serialize_uri() == fulfillment_threshold['fulfillment_uri']
         assert parsed_fulfillment.condition.serialize_uri() == fulfillment.condition.serialize_uri()
-        assert parsed_fulfillment.serialize_json() == fulfillment.serialize_json()
+        assert parsed_fulfillment.to_dict() == fulfillment.to_dict()
 
-    def test_deserialize_json_unsigned(self, vk_ilp):
+    def test_deserialize_unsigned_dict_to_fulfillment(self, vk_ilp):
         fulfillment = ThresholdSha256Fulfillment(threshold=1)
         fulfillment.add_subfulfillment(Ed25519Fulfillment(public_key=VerifyingKey(vk_ilp['b58'])))
         fulfillment.add_subfulfillment(Ed25519Fulfillment(public_key=VerifyingKey(vk_ilp['b58'])))
-        fulfillment_json = json.loads(fulfillment.serialize_json())
-        parsed_fulfillment = fulfillment.from_json(fulfillment_json)
+        parsed_fulfillment = fulfillment.from_dict(fulfillment.to_dict())
 
         assert parsed_fulfillment.condition.serialize_uri() == fulfillment.condition.serialize_uri()
-        assert parsed_fulfillment.serialize_json() == fulfillment.serialize_json()
+        assert parsed_fulfillment.to_dict() == fulfillment.to_dict()
 
     def test_weights(self, fulfillment_ed25519):
         ilp_fulfillment = Fulfillment.from_uri(fulfillment_ed25519['fulfillment_uri'])
 
         fulfillment1 = ThresholdSha256Fulfillment(threshold=2)
         fulfillment1.add_subfulfillment(ilp_fulfillment, weight=2)
-        fulfillment_json = json.loads(fulfillment1.serialize_json())
-        parsed_fulfillment1 = fulfillment1.from_json(fulfillment_json)
+        parsed_fulfillment1 = fulfillment1.from_dict(fulfillment1.to_dict())
 
         assert parsed_fulfillment1.condition.serialize_uri() == fulfillment1.condition.serialize_uri()
-        assert parsed_fulfillment1.serialize_json() == fulfillment1.serialize_json()
+        assert parsed_fulfillment1.to_dict() == fulfillment1.to_dict()
         assert parsed_fulfillment1.subconditions[0]['weight'] == 2
         assert parsed_fulfillment1.validate(MESSAGE) is True
 
         fulfillment2 = ThresholdSha256Fulfillment(threshold=3)
         fulfillment2.add_subfulfillment(ilp_fulfillment, weight=2)
-        fulfillment_json = json.loads(fulfillment2.serialize_json())
-        parsed_fulfillment2 = fulfillment1.from_json(fulfillment_json)
+        parsed_fulfillment2 = fulfillment1.from_dict(fulfillment2.to_dict())
 
         assert parsed_fulfillment2.subconditions[0]['weight'] == 2
         assert parsed_fulfillment2.validate(MESSAGE) is False
 
         fulfillment3 = ThresholdSha256Fulfillment(threshold=3)
         fulfillment3.add_subfulfillment(ilp_fulfillment, weight=3)
-        fulfillment_json = json.loads(fulfillment3.serialize_json())
-        parsed_fulfillment3 = fulfillment1.from_json(fulfillment_json)
+        parsed_fulfillment3 = fulfillment1.from_dict(fulfillment3.to_dict())
 
         assert parsed_fulfillment3.condition.serialize_uri() == fulfillment3.condition.serialize_uri()
         assert not (fulfillment3.condition.serialize_uri() == fulfillment1.condition.serialize_uri())
@@ -506,8 +490,7 @@ class TestInvertedThresholdSha256Fulfillment:
 
         fulfillment = InvertedThresholdSha256Fulfillment(threshold=1)
         fulfillment.add_subfulfillment(ilp_fulfillment_ed)
-        fulfillment_json = json.loads(fulfillment.serialize_json())
-        parsed_fulfillment = fulfillment.from_json(fulfillment_json)
+        parsed_fulfillment = fulfillment.from_dict(fulfillment.to_dict())
 
         assert parsed_fulfillment.condition_uri == fulfillment.condition_uri
         assert parsed_fulfillment.serialize_uri() == fulfillment.serialize_uri()
@@ -521,16 +504,14 @@ class TestTimeoutFulfillment:
     def test_serialize_condition_and_validate_fulfillment(self):
 
         fulfillment = TimeoutFulfillment(expire_time=timestamp())
-        fulfillment_json = json.loads(fulfillment.serialize_json())
-        parsed_fulfillment = fulfillment.from_json(fulfillment_json)
+        parsed_fulfillment = fulfillment.from_dict(fulfillment.to_dict())
 
         assert parsed_fulfillment.condition_uri == fulfillment.condition_uri
         assert parsed_fulfillment.serialize_uri() == fulfillment.serialize_uri()
         assert parsed_fulfillment.validate(now=timestamp()) is False
 
-        fulfillment = TimeoutFulfillment(expire_time=str(float(timestamp())+1000))
-        fulfillment_json = json.loads(fulfillment.serialize_json())
-        parsed_fulfillment = fulfillment.from_json(fulfillment_json)
+        fulfillment = TimeoutFulfillment(expire_time=str(float(timestamp()) + 1000))
+        parsed_fulfillment = fulfillment.from_dict(fulfillment.to_dict())
 
         assert parsed_fulfillment.condition_uri == fulfillment.condition_uri
         assert parsed_fulfillment.serialize_uri() == fulfillment.serialize_uri()
@@ -573,8 +554,7 @@ class TestEscrow:
         fulfillment_escrow.add_subfulfillment(fulfillment_and_execute)
         fulfillment_escrow.add_subfulfillment(fulfillment_and_abort)
 
-        fulfillment_json = json.loads(fulfillment_escrow.serialize_json())
-        parsed_fulfillment = fulfillment_escrow.from_json(fulfillment_json)
+        parsed_fulfillment = fulfillment_escrow.from_dict(fulfillment_escrow.to_dict())
 
         assert parsed_fulfillment.condition_uri == fulfillment_escrow.condition_uri
         assert parsed_fulfillment.serialize_uri() == fulfillment_escrow.serialize_uri()