Browse Source

Added support for LongInt and ULongInt. (#52)

* Added support for LongInt and ULongInt.

Improved error handling. Added more checks.

* Further String de/serialising improvements.
Brucey 1 month ago
parent
commit
218e120bcd
2 changed files with 200 additions and 10 deletions
  1. 168 8
      jconv.mod/jconv.bmx
  2. 32 2
      jconv.mod/tests/test.bmx

+ 168 - 8
jconv.mod/jconv.bmx

@@ -1,4 +1,4 @@
-' Copyright (c) 2019-2020 Bruce A Henderson
+' Copyright (c) 2019-2025 Bruce A Henderson
 '
 ' This software is provided 'as-is', without any express or implied
 ' warranty. In no event will the authors be held liable for any damages
@@ -26,11 +26,13 @@ bbdoc: JSON Object de/serializer.
 End Rem
 Module Text.JConv
 
-ModuleInfo "Version: 1.06"
+ModuleInfo "Version: 1.07"
 ModuleInfo "Author: Bruce A Henderson"
 ModuleInfo "License: zlib/png"
-ModuleInfo "Copyright: 2019-2020 Bruce A Henderson"
+ModuleInfo "Copyright: 2019-2025 Bruce A Henderson"
 
+ModuleInfo "History: 1.07"
+ModuleInfo "History: Added support for LongInt and ULongInt types."
 ModuleInfo "History: 1.06"
 ModuleInfo "History: Added support for transient, noSerialize and noDeserialize field metadata."
 ModuleInfo "History: 1.05"
@@ -103,6 +105,8 @@ Type TJConvBuilder
 		RegisterSerializer("TULong", New TULongSerializer)
 		RegisterSerializer("TFloat", New TFloatSerializer)
 		RegisterSerializer("TDouble", New TDoubleSerializer)
+		RegisterSerializer("TLongInt", New TLongIntSerializer)
+		RegisterSerializer("TULongInt", New TULongIntSerializer)
 		Return Self
 	End Method
 
@@ -196,7 +200,15 @@ Type TJConv
 
 	Method FromJson:Object(txt:String, typeId:TTypeId, obj:Object)
 		Local error:TJSONError
-		Local json:TJSON = TJSON.Load(txt, 0, error)
+		Local flags:Int = 0
+		If typeId = StringTypeId Then
+			flags :| JSON_DECODE_ANY
+		End If
+		Local json:TJSON = TJSON.Load(txt, flags, error)
+
+		If error Then
+			Throw TJconvJsonException.Create(error)
+		End If
 
 		Return FromJson(json, typeId, obj)
 	End Method
@@ -214,6 +226,10 @@ Type TJConv
 		Local error:TJSONError
 		Local json:TJSON = TJSON.Load(stream, 0, error)
 
+		If error Then
+			Throw TJconvJsonException.Create(error)
+		End If
+
 		Return FromJson(json, typeId, obj)
 	End Method
 
@@ -233,6 +249,11 @@ Type TJConv
 	End Rem
 	Method ToJson:String(obj:Object)
 		If Not obj Then
+
+			If ObjectIsString(obj) Then
+				Return "~q~q"
+			End If
+
 			If IsEmptyArray(obj) Then
 				Return "[]"
 			End If
@@ -241,6 +262,12 @@ Type TJConv
 		End If
 		
 		Local typeId:TTypeId = TTypeId.ForObject(obj)
+
+		If typeId = StringTypeId Then
+			Local json:TJSONString = New TJSONString.Create(String(obj))
+
+			Return json.SaveString(flags | JSON_ENCODE_ANY, 0, precision)
+		End If
 		
 		If typeId.ExtendsType(ArrayTypeId) Then
 			Local json:TJSONArray = New TJSONArray.Create()
@@ -378,7 +405,13 @@ Type TJConv
 
 				Case DoubleTypeId
 					j = serializer.Serialize(f.GetDouble(obj), fieldType.Name())
-					
+
+				Case LongIntTypeId
+					j = serializer.Serialize(f.GetLongInt(obj), fieldType.Name())
+
+				Case ULongIntTypeId
+					j = serializer.Serialize(f.GetULongInt(obj), fieldType.Name())
+
 				Case StringTypeId
 					Local s:String = f.GetString(obj)
 					If s Then
@@ -425,6 +458,11 @@ Type TJConv
 	End Method
 	
 	Method ProcessArrayToJson(json:TJSONArray, typeId:TTypeId, array:Object)
+
+		If IsEmptyArray(array) Then
+			Return
+		End If
+
 		Local dims:Int
 		Try
 			dims = typeId.ArrayDimensions(array)
@@ -585,6 +623,14 @@ Type TJConvSerializer
 		Return New TJSONReal.Create(source)
 	End Method
 
+	Method Serialize:TJSON(source:LongInt, sourceType:String)
+		Return New TJSONInteger.Create(source)
+	End Method
+
+	Method Serialize:TJSON(source:ULongInt, sourceType:String)
+		Return New TJSONInteger.Create(source)
+	End Method
+
 	Method Serialize:TJSON(source:String, sourceType:String)
 		Return New TJSONString.Create(source)
 	End Method
@@ -597,6 +643,17 @@ Type TJConvSerializer
 	
 	Method Deserialize:Object(json:TJSON, typeId:TTypeId, obj:Object)
 		If TJSONObject(json) Then
+
+			' we don't deserialize objects to String type
+			If typeId = StringTypeId Then
+				Throw TJconvDeserializeException.Create("Deserializing String but found Object type.")
+			End If
+
+			' we don't deserialize objects to Array type
+			IF typeId.ExtendsType(ArrayTypeId) Then
+				Throw TJconvDeserializeException.Create("Deserializing Array but found Object type.")
+			End If
+
 			If Not obj Then
 				obj = typeId.NewObject()
 			End If
@@ -692,14 +749,20 @@ Type TJConvSerializer
 								Continue
 						End Select
 						
-						If fieldType.ExtendsType(ArrayTypeId) Or fieldType.ExtendsType(ObjectTypeId) Then
+						If fieldType.ExtendsType(ArrayTypeId)
+
+							Throw TJconvDeserializeException.Create("Deserializing String but found Array type '" + fieldType.Name() + "' : " + j.key)
 						
+						End If
+
+						If fieldType.ExtendsType(ObjectTypeId) Then
+
 							Local fobj:Object = jconv.FromJson(j, fieldType, Null)
 						
 							If fobj Then
 								f.Set(obj, fobj)
 							End If
-						
+
 						End If
 
 						Continue
@@ -729,6 +792,10 @@ Type TJConvSerializer
 				End If
 			Next
 		Else If TJSONArray(json) Then
+
+			If typeId = StringTypeId Then
+				Throw TJconvDeserializeException.Create("Deserializing String but found Array type.")
+			End If
 			
 			obj = Deserialize(TJSONArray(json), typeId, obj)
 		
@@ -746,7 +813,7 @@ Type TJConvSerializer
 		Local size:Int = jsonArray.Size()
 
 		If Not size Then
-			Return typeId.NewArray()
+			Return typeId.NullValue()
 		End If
 
 		Local elementType:TTypeId = typeId.ElementType()
@@ -929,6 +996,27 @@ Type TDouble
 
 End Type
 
+Type TLongInt
+
+	Field value:LongInt
+
+	Method New(value:LongInt)
+		Self.value = value
+	End Method
+
+End Type
+
+Type TULongInt
+
+	Field value:ULongInt
+
+	Method New(value:ULongInt)
+		Self.value = value
+	End Method
+
+End Type
+
+
 Type TBoolSerializer Extends TJConvSerializer
 
 	Method Serialize:TJSON(source:Object, sourceType:String) Override
@@ -1139,3 +1227,75 @@ Type TDoubleSerializer Extends TJConvSerializer
 	End Method
 	
 End Type
+
+Type TLongIntSerializer Extends TJConvSerializer
+
+	Method Serialize:TJSON(source:Object, sourceType:String) Override
+		Local value:TLongInt = TLongInt(source)
+		If value Then
+			Return New TJSONInteger.Create(value.value)
+		End If
+	End Method
+
+	Method Deserialize:Object(json:TJSON, typeId:TTypeId, obj:Object) Override
+		If TJSONInteger(json) Then
+			If Not obj Then
+				obj = New TLongInt(LongInt(TJSONInteger(json).Value()))
+			End If
+		End If
+		
+		Return obj
+	End Method
+	
+End Type
+
+Type TULongIntSerializer Extends TJConvSerializer
+
+	Method Serialize:TJSON(source:Object, sourceType:String) Override
+		Local value:TULongInt = TULongInt(source)
+		If value Then
+			Return New TJSONInteger.Create(value.value)
+		End If
+	End Method
+
+	Method Deserialize:Object(json:TJSON, typeId:TTypeId, obj:Object) Override
+		If TJSONInteger(json) Then
+			If Not obj Then
+				obj = New TULongInt(ULongInt(TJSONInteger(json).Value()))
+			End If
+		End If
+		
+		Return obj
+	End Method
+	
+End Type
+
+Type TJconvJsonException Extends TBlitzException
+	Field error:TJSONError
+
+	Function Create:TJconvJsonException(error:TJSONError)
+		Local ex:TJconvJsonException = New TJconvJsonException
+		ex.error = error
+		Return ex
+	End Function
+
+	Method ToString:String()
+		If error Then
+			Return error.text
+		End If
+	End Method
+End Type
+
+Type TJconvDeserializeException Extends TBlitzException
+	Field error:String
+
+	Function Create:TJconvDeserializeException(error:String)
+		Local ex:TJconvDeserializeException = New TJconvDeserializeException
+		ex.error = error
+		Return ex
+	End Function
+
+	Method ToString:String()
+		Return error
+	End Method
+End Type

+ 32 - 2
jconv.mod/tests/test.bmx

@@ -40,13 +40,15 @@ Type TArrayTest Extends TJConvTest
 	Const JSON_BOX_SIZE_T:String = "{~qb8~q: 100}"
 	Const JSON_BOX_FLOAT:String = "{~qb9~q: 7.5}"
 	Const JSON_BOX_DOUBLE:String = "{~qb10~q: 68.418}"
-	Const JSON_PREC:String = "{~qp1~q: 5.352, ~qp2~q: 65.698}"
+	Const JSON_PREC:String = "{~qp1~q: 5.352, ~qp2~q: 65.7}"
 	Const JSON_SER_NAME_COMPACT:String = "{~qname~q:~qone~q,~qname1~q:~qtwo~q,~qc~q:~qthree~q}"
 	Const JSON_SER_NAME_PRETTY:String = "{~n  ~qname~q: ~qone~q,~n  ~qname1~q: ~qtwo~q,~n  ~qc~q: ~qthree~q~n}"
 	Const JSON_TRANS_NO_B:String = "{~qa~q: ~qone~q, ~qc~q: ~qthree~q}"
 	Const JSON_TRANS:String = "{~qa~q: ~qone~q, ~qb~q: ~qtwo~q, ~qc~q: ~qthree~q}"
 	Const JSON_IGNORE_SER:String = "{~qa~q: ~qone~q, ~qc~q: ~qthree~q}"
 	Const JSON_IGNORE:String = "{~qa~q: ~qone~q, ~qb~q: ~qtwo~q, ~qc~q: ~qthree~q, ~qd~q: ~qfour~q}"
+	Const JSON_STRING_ARRAY:String = "{~qvalues~q: [~qOne~q, ~qTwo~q, ~qThree~q], ~qother_values~q: []}"
+	Const JSON_STRING:String = "~qHello world~q"
 
 	Method testEmptyObject() { test }
 		Local obj:Object
@@ -317,7 +319,7 @@ Type TArrayTest Extends TJConvTest
 
 		Local prec:TPrec = New TPrec(5.3521, 65.6982902)
 
-		jconv = New TJConvBuilder.WithPrecision(3).Build()
+		jconv = New TJConvBuilder.WithPrecision(4).Build()
 		
 		assertEquals(JSON_PREC, jconv.ToJson(prec))
 
@@ -390,6 +392,29 @@ Type TArrayTest Extends TJConvTest
 		assertNull(ignored.d)
 	End Method
 
+	Method testStringArray() { test }
+		
+		Local array:TStringArray = New TStringArray
+		array.values = ["One", "Two", "Three"]
+		
+		assertEquals(JSON_STRING_ARRAY, jconv.ToJson(array))
+		
+		array = TStringArray(jconv.FromJson(JSON_STRING_ARRAY, "TStringArray"))
+		assertEquals(3, array.values.length)
+		assertEquals("One", array.values[0])
+		assertEquals("Two", array.values[1])
+		assertEquals("Three", array.values[2])
+	End Method
+
+	Method testString() { test }
+		
+		Local str:String = String(jconv.FromJson(JSON_STRING, "String"))
+		
+		assertEquals("Hello world", str)
+		
+		assertEquals(JSON_STRING, jconv.ToJson(str))
+	End Method
+
 End Type
 
 Type TData
@@ -580,3 +605,8 @@ Type TIgnored
 	Field c:String { noDeserialize }
 	Field d:String { noSerialize noDeserialize }
 End Type
+
+Type TStringArray
+	Field values:String[]
+	Field other_values:String[]
+End Type