source: pyson/test/DeserializerTest.py@ 748

Last change on this file since 748 was 748, checked in by wouter, 11 months ago

#257 added test showing issue when parse list as Collection.

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