Browse Source

Changed headings. Added builder section.

woollybah 5 years ago
parent
commit
2b5459fd78
1 changed files with 164 additions and 7 deletions
  1. 164 7
      jconv.mod/doc/intro.bbdoc

+ 164 - 7
jconv.mod/doc/intro.bbdoc

@@ -1,4 +1,4 @@
-### Serialising with JConv
+## Serialising with JConv
 
 In the context of #BRL.JConv, serialisation is the mapping of BlitzMax objects to their JSON representation.
 
@@ -75,7 +75,7 @@ Type TUser
 End Type
 ```
 
-### Deserialising with JConv
+## Deserialising with JConv
 
 We'll start by creating a #String containing the JSON to convert :
 ```blitzmax
@@ -124,7 +124,7 @@ Type TUser
 End Type
 ```
 
-### Serialising Nested Objects
+## Serialising Nested Objects
 
 #BRL.JConv can also handle the conversion of more complex objects that include the nesting of other non-primitive objects.
 To demostrate this we will extend the `TUser` type to include an address, which will be represented by the `TAddress` #Type :
@@ -161,7 +161,7 @@ We'll initially create the required BlitzMax objects :
 Local address:TAddress = New TAddress("66 Some Street", "Someville", "Someland")
 Local user:TUser = New TUser("bob", "[email protected]", 30, address)
 ```
-And then serialise the user with an instance of #TJCon :
+And then serialise the user with an instance of #TJConv :
 ```blitzmax
 Local jconv:TJConv = New TJConvBuilder.Build()
 Local json:String = jconv.ToJson(user)
@@ -172,7 +172,7 @@ The resulting conversion to JSON is :
 ```
 As you can see, #BRL.JConv has correctly nested the address inside the user as a JSON object.
 
-### Deserialising Nested Objects
+## Deserialising Nested Objects
 
 In the real world, the developer is often presented with a JSON API from which they need to construct the relevant BlitzMax
 Types in order to import the data.
@@ -314,7 +314,7 @@ Type TLocation
 End Type
 ```
 
-### Customising Field Names
+## Customising Field Names
 
 Occasionally, a JSON object will use a key that has the same name as a reserved keyword in BlitzMax. In that case, you are unable create a field
 using the desired name. Fortunately, #BRL.JConv allows you use metadata to specify the serialised name of a given field using the `serializedName`
@@ -407,7 +407,7 @@ deserialising the JSON would result in the `name` #Field containing the value `u
 }
 ```
 
-### Ignoring Fields
+## Ignoring Fields
 
 If you don't want a field to be mapped to or from JSON there are some metadata properties that you can apply to your types in order to do so.
 The first, `transient`, completely disables field from mapping in either direction.
@@ -469,3 +469,160 @@ Type TUser
 End Type
 ```
 
+## Configuring TJConv with the Builder
+
+You may have noticed, that by default #BRL.JConv serialises the JSON into a single line.
+You can change this behaviour with one ofthe builder's configurable options.
+
+The builder uses what is known as a fluent interface, or method chaining design, where a sequence of method calls can be used to construct the #TJConv instance.
+
+For example, the following builder creates an instance of #TJConv which will serialise objects to JSON with a decimal a precision of 2 places and compact objects :
+```blitzmax
+Local jconv:TJConv = New TJConvBuilder.WithPrecision(2).WithCompact().Build()
+```
+
+### WithIndent
+
+The #WithIndent method of #TJConvBuilder specifies the number of spaces to use for indenting of nested objects. The default of 0 (zero)
+means not to use pretty-printing.
+
+This is an example of `TUser` using the default options :
+```json
+{"name": "Bob", "email": "[email protected]", "age": 30}
+```
+And this is an example of building with #WithIndent :
+```json
+{
+  "name": "Bob",
+  "email": "[email protected]",
+  "age": 30
+}
+```
+
+### WithCompact
+
+On the other hand, JSON can be compacted further using the #WithCompact method, which works to remove extra spaces :
+```json
+{"name":"Bob","email":"[email protected]","age":30}
+```
+### WithPrecision
+The representation of decimal numbers can be controlled by the #WithPrecision method, which specifies the maximum number of decimal places to used.
+
+For example, the default representation of a #Type `TPoint` :
+```blitzmax
+Type TPoint
+	Field x:Double
+	Field y:Double
+End Type
+```
+would normally result in the following JSON with fields of the values (10.565, 15.912) :
+```json
+{"x": 10.565, "y": 15.912000000000001}
+```
+Using a maximum precision of 3 (`WithPrecision(3)`), the resulting JSON would become :
+```json
+{"x": 10.565, "y": 15.912}
+```
+
+### WithEmptyArrays
+
+By default, #Null/empty arrays are not serialised at all. That is, the field is not included in the JSON object.
+The #WithEmptyArrays option can be enabled to generate an empty array (`[]`] instead.
+
+### WithBoxing
+
+Primitive numbers, by their very nature in BlitzMax, have no concept of nullability. JSON, conversely, can represent any field as a null value,
+either by simply not including it in the object, or by having the value `null`.
+
+To support this, #BRL.JConv provides an option to use "boxed" primitives in your types. A Boxed primitive is just an instance of a #Type that has
+a value field of the appropriate numeric #Type. Using a boxed primitive then allows a field to contain a value, or be #Null.
+
+This feature is enabled by using the #WithBoxing option of the builder.
+
+As an example, suppose there is a JSON object which has a numeric field `failures`. The schema specifies that this value can either be `null` or have a value
+greater than zero :
+```json
+[
+  {
+    "jobId": "ABC123",
+    "failures": 3,
+    "lastError": "overflow"
+  },
+  {
+    "jobId": "DEF456"
+  }
+]
+```
+Deserialising this wouldn't be a problem, as our `TJob` #Type could represent no `failures` by the number zero :
+```blitzmax
+Type TJob
+	Field jobId:String
+	Field failures:Int
+	Field lastError:String
+End Type
+```
+However, were we required to serialise our #Type to JSON for use by the API, we'd potentially fail schema validation by passing zero as a value for
+the `failures` #Field.
+
+Utilising the boxing feature, we could instead define the `failures` #Field as `TInt` :
+```blitzmax
+Type TJob
+	Field jobId:String
+	Field failures:TInt
+	Field lastError:String
+End Type
+```
+Which would, for #Null values, result in the `features` #Field not being serialized to JSON.
+
+Here's a full example highlighting the use of boxing :
+```blitzmax
+SuperStrict
+
+Framework BRL.StandardIO
+Import BRL.JConv
+
+Local job1:TJob = New TJob("ABC123", 3, "overflow")
+Local job2:TBoxedJob = New TBoxedJob("DEF456", 0, Null)
+
+Local jconv:TJConv = New TJConvBuilder.WithBoxing().WithIndent(2).Build()
+
+Print jconv.ToJson(job1)
+Print jconv.ToJson(job2)
+
+Type TJob
+	Field jobId:String
+	Field failures:Int
+	Field lastError:String
+	
+	Method New(jobId:String, failures:Int, lastError:String)
+		Self.jobId = jobId
+		Self.failures = failures
+		Self.lastError = lastError
+	End Method
+End Type
+
+Type TBoxedJob
+	Field jobId:String
+	Field failures:TInt
+	Field lastError:String
+
+	Method New(jobId:String, failures:Int, lastError:String)
+		Self.jobId = jobId
+		If failures > 0 Then
+			Self.failures = New TInt(failures)
+		End If
+		Self.lastError = lastError
+	End Method
+End Type
+```
+Running the above example would result in the following output :
+```
+{
+  "jobId": "ABC123",
+  "failures": 3,
+  "lastError": "overflow"
+}
+{
+  "jobId": "DEF456"
+}
+```