source: pyson/test/DeserializerTest.py@ 659

Last change on this file since 659 was 572, checked in by wouter, 18 months ago

#192 pyson @JsonSerialize now takes class instead of str

File size: 5.5 KB
Line 
1
2from abc import ABC
3from datetime import datetime
4from decimal import Decimal
5import json
6import re
7import sys, traceback
8from typing import Dict, List, Set, Any, Union, Optional
9import unittest
10from uuid import uuid4, UUID
11
12from pyson.Deserializer import Deserializer
13from pyson.Serializer import Serializer
14from pyson.JsonSerialize import JsonSerialize
15from pyson.JsonDeserialize import JsonDeserialize
16from pyson.JsonGetter import JsonGetter
17from pyson.JsonSubTypes import JsonSubTypes
18from pyson.JsonTypeInfo import Id, As
19from pyson.JsonTypeInfo import JsonTypeInfo
20from pyson.JsonValue import JsonValue
21from pyson.ObjectMapper import ObjectMapper
22from pickle import NONE
23from test.MyDeserializer import ValueDeserializer2
24
25# deserializer DROPS FIRST CHAR from string and assumes rest is an int.
26# Then returns Simple(int)
27class ValueDeserializer(Deserializer):
28 def __hash__(self):
29 return hash(self.geta())
30 def deserialize(self, data:object, clas: object)-> object:
31 if type(data)!=str:
32 raise ValueError("Expected str starting with '$', got "+str(data))
33 return Simple(int(data[1:]))
34
35# serializes Simple object, just prefixing its value (as string) with "$"
36class ValueSerializer(Serializer):
37 def serialize(self, obj:object)-> object:
38 if not isinstance(obj, Simple):
39 raise ValueError("Expected Dimple object")
40 return "$" + str(obj.geta())
41
42class Basic:
43 def __init__(self, v:float):
44 self._v=v
45 def __eq__(self, other):
46 return isinstance(other, self.__class__) and \
47 self._v==other._v
48 def getV(self):
49 return self._v
50 def __repr__(self):
51 return "Basic:"+str(self._v)
52 def __hash__(self):
53 return hash(self._v)
54
55@JsonDeserialize(ValueDeserializer)
56@JsonSerialize(ValueSerializer)
57class Simple:
58 def __init__(self, a:int):
59 self._a=a
60 def geta(self)->int:
61 return self._a
62 def __eq__(self, other):
63 return isinstance(other, self.__class__) and \
64 self._a==other._a
65 def __repr__(self):
66 return "Simple:"+str(self._a)
67 def __hash__(self):
68 return hash(self._a)
69
70
71
72@JsonDeserialize(ValueDeserializer2)
73class Simple2:
74 def __init__(self, a:int):
75 self._a=a
76 def geta(self)->int:
77 return self._a
78 def __eq__(self, other):
79 return isinstance(other, self.__class__) and \
80 self._a==other._a
81 def __repr__(self):
82 return self._name+","+str(self._a)
83
84#None cancels out the existing deserializer.
85# parsing with str should now fail.
86@JsonDeserialize(None)
87class Simple3 (Simple):
88 pass
89
90
91class MyList:
92 def __init__(self, data: List[Simple] ):
93 self.data=data
94 def getData(self)->List[Simple]:
95 return self.data
96
97class BasicDict:
98 def __init__(self, data: Dict[Basic,Basic] ):
99 self.data=data
100 def getData(self)->Dict[Basic,Basic]:
101 return self.data
102 def __repr__(self):
103 return "BasicDict:"+str(self.data)
104 def __eq__(self, other):
105 return isinstance(other, self.__class__) and \
106 self.data==other.data
107
108
109class SimpleDict:
110 def __init__(self, data: Dict[Simple,Simple] ):
111 self.data=data
112 def getData(self)->Dict[Simple,Simple]:
113 return self.data
114 def __eq__(self, other):
115 return isinstance(other, self.__class__) and \
116 self.data==other.data
117 def __repr__(self):
118 return "SimpleDict:"+str(self.data)
119
120
121class DeserializerTest(unittest.TestCase):
122 '''
123 Test a lot of back-and-forth cases.
124 FIXME Can we make this a parameterized test?
125 '''
126 pyson=ObjectMapper()
127
128 def testDeserialize(self):
129 objson= "$12"
130 self.assertEqual(Simple(12), self.pyson.parse(objson, Simple))
131
132 def testExternalDeserialize2(self):
133 objson= "$13"
134 self.assertEqual(13, self.pyson.parse(objson, Simple2))
135
136
137 def testExternalDeserialize3(self):
138 objson= "$13"
139 self.assertRaises(ValueError, lambda:self.pyson.parse(objson, Simple3))
140
141 def testDeserializeMyList(self):
142 print(self.pyson.toJson(MyList([12,13])))
143
144 # the json we provide is NOT the proper json but a STRING.
145 # This triggers a fallback mechanism that tries to parse the string as json.
146 objson={"data": ["$12", "$13"]}
147 res = self.pyson.parse(objson, MyList)
148 print(res)
149 self.assertEqual([Simple(12),Simple(13)], res.data)
150
151
152 def testSerializeBasicDict(self):
153 '''
154 Basic object keys. Special (de)serializer should kick in #190
155 '''
156 d= BasicDict( { Basic(1.):Basic(2.), Basic(3.): Basic(4.) } )
157 objson={"data": {"{\"v\": 1.0}": {"v": 2.0}, "{\"v\": 3.0}": {"v": 4.0}}}
158 dump=json.dumps(self.pyson.toJson(d));
159 print(dump)
160 # self.assertEqual(objson, dump);
161 res=self.pyson.parse(objson, BasicDict)
162 print("res="+str(res))
163 self.assertEqual(d, res)
164
165
166 def testSerializeSimpleDictCustomSerializer(self):
167 d= SimpleDict( { Simple(1):Simple(2), Simple(3): Simple(4) } )
168
169 # The keys need extra quotes, they are deserialied by
170 # our special deserializer that parses the string as json,
171 # and json requires double quotes around its strings.
172 objson = {"data": {'"$1"': "$2", '"$3"': "$4"}}
173
174 obj=self.pyson.toJson(d)
175 print(json.dumps(obj))
176 self.assertEqual(objson, obj)
177
178 res = self.pyson.parse(objson, SimpleDict)
179 print("res="+str(res))
180 self.assertEqual(d, res)
181
Note: See TracBrowser for help on using the repository browser.