IC4J API Docs
  • Overview
    • Introduction
  • Quick Start
  • License
  • Reference
    • API Reference
      • Install IC4J Libraries
      • Supported Types
      • ReplicaTransport
      • Identity
      • Principal
      • AgentBuilder
      • ProxyBuilder
      • Using IDLArgs
      • QueryBuilder and UpdateBuilder
      • Using Raw Agent Methods
      • Handle Binary Payloads
      • Object Serializers and Deserializers
        • Pojo Serializer and Deserializer
        • JSON Jackson Serializer and Deserializer
        • JSON Gson Serializer and Deserializer
        • XML DOM Serializer and Deserializer
        • XML JAXB Serializer and Deserializer
        • JDBC Serializer
      • Android Development
Powered by GitBook
On this page
  1. Reference
  2. API Reference
  3. Object Serializers and Deserializers

JSON Jackson Serializer and Deserializer

PreviousPojo Serializer and DeserializerNextJSON Gson Serializer and Deserializer

Last updated 1 year ago

Use and to serialize and deserialize JSON object to and from the Candid payload of type RECORD.

A fully functional example using JacksonSerializer and JacksonDeserializer can be found .

This example uses Motoko to call the canister . The canister uses 2 complex types, LoanApplication and LoanOffer.

main.mo
// Loan Application
public type LoanApplication = {
    id: Nat;
    firstname: Text;
    lastname: Text;
    zipcode: Text;
    ssn: Text;
    amount: Float;
    term: Nat16;
    created: Int;
 };

// Loan Offer
public type LoanOffer = {
    providerid: Principal;
    providername: Text;
    applicationid: Nat;
    apr: Float;
    created: Int;
};

The canister has 2 methods: apply and getOffers.

main.mo
public shared (msg) func apply(input : LoanApplication) : async LoanOffer { 
       counter += 1;
        Debug.print("Loan Application for user " #Principal.toText(msg.caller));
        
        let offer  : LoanOffer = {
            providerid = Principal.fromActor(this);
            providername = "Loan Provider";
            applicationid = counter;
            apr = 3.14;
            created = Time.now();
        };

        var userOffers :  ?Offers<LoanOffer> = offers.get(msg.caller);

        switch userOffers {
            case (null) { var userOffer : Offers<LoanOffer> = Buffer.Buffer(0); userOffer.add(offer);  offers.put(msg.caller, userOffer)};
            case (?userOffer) { userOffer.add(offer); };
        };
        return offer;
};

public query (msg) func getOffers() : async [LoanOffer] {
        var userOffers :  ?Offers<LoanOffer> = offers.get(msg.caller);

        switch userOffers {
            case (null) { return [] };
            case (?userOffer) { return userOffer.toArray() };
        };
};
LoanApplication.json
{
"id" : 0,
"firstname" : "John",
"lastname" : "Doe",
"zipcode" : "99999",
"ssn" : "111-11-1111",
"amount" : 2000.00,
"term" : 24,
"created" : 0
}
Main.java
Map<Label,IDLType> applicationRecord = new TreeMap<Label,IDLType>();
applicationRecord.put(Label.createNamedLabel("id"), IDLType.createType(Type.NAT));
applicationRecord.put(Label.createNamedLabel("firstname"), IDLType.createType(Type.TEXT));
applicationRecord.put(Label.createNamedLabel("lastname"), IDLType.createType(Type.TEXT));
applicationRecord.put(Label.createNamedLabel("zipcode"), IDLType.createType(Type.TEXT));
applicationRecord.put(Label.createNamedLabel("ssn"), IDLType.createType(Type.TEXT));		
applicationRecord.put(Label.createNamedLabel("amount"), IDLType.createType(Type.FLOAT64));
applicationRecord.put(Label.createNamedLabel("term"), IDLType.createType(Type.NAT16));
applicationRecord.put(Label.createNamedLabel("created"), IDLType.createType(Type.INT));
		
IDLType idlType =  IDLType.createType(Type.RECORD, applicationRecord);
		
Map<Label,IDLType> offerRecord = new TreeMap<Label,IDLType>();
offerRecord.put(Label.createNamedLabel("providerid"), IDLType.createType(Type.PRINCIPAL));
offerRecord.put(Label.createNamedLabel("providername"), IDLType.createType(Type.TEXT));
offerRecord.put(Label.createNamedLabel("applicationid"), IDLType.createType(Type.NAT));	
offerRecord.put(Label.createNamedLabel("apr"), IDLType.createType(Type.FLOAT64));		
offerRecord.put(Label.createNamedLabel("created"), IDLType.createType(Type.INT));
		
IDLType resultIdlType =  IDLType.createType(Type.RECORD, offerRecord);	

Next, create IDLValue using the JacksonSerializer create method.

Main.java
JsonNode jsonValue = readNode(LOAN_APPLICATION_FILE);
		
IDLValue idlValue = IDLValue.create(jsonValue, JacksonSerializer.create(idlType));
List<IDLValue> idlArgs = new ArrayList<IDLValue>();
idlArgs.add(idlValue);

byte[] buf = IDLArgs.create(idlArgs).toBytes();
Main.java
CompletableFuture<byte[]> response = UpdateBuilder.create(agent,Principal.fromString(icCanister), "apply").arg(buf).callAndWait(Waiter.create(60, 5));
		
byte[] output = response.get();
JsonNode jsonResult = IDLArgs.fromBytes(output).getArgs().get(0)
			.getValue(JacksonDeserializer.create(resultIdlType), JsonNode.class);

The example uses the file with JSON as an input.

To be able to properly map JSON names and values to Candid name types declare the structure as follows:

The Serializer input is the variable type .

Use, or to call the Canister and deserialize output to .

JacksonSerializer
JacksonDeserializer
Java Jackson
here
main.mo
LoanApplication payload
JsonNode
Raw Methods
JsonNode
UpdateBuilder
QueryBuilder
IDLType