Search code examples
nearprotocol

How to serialize PersistentMap and return it


I have a simple map<string, string> and would like to add to it and return it serialized. Here is my code

organizations: PersistentMap<string, string> = new PersistentMap<
    string,
    string
  >("oc"); 

getOrgList(): PersistentMap<string, string> {
    return this.organizations;
  }

The contract call panics as below:

kind: {
    ExecutionError: 'Smart contract panicked: Cannot parse JSON, filename: "~lib/assemblyscript-json/decoder.ts" line: 144 col: 5'      
  },

Update: When the map is empty, I get no errors. I add items to the map using

this.organizations.set(orgCode, orgName);

and I call it from the command line like that

near call cert.msaudi.testnet createOrgId '{\"orgCode\":\"AAA\",\"orgName\":\"AAAA\"}' --accountId=msaudi.testnet

edit:full contract code

import { Context, PersistentMap } from "near-sdk-core";

@nearBindgen
export class Contract {
  public organizations: PersistentMap<string, string> = new PersistentMap<
    string,
    string
  >("oc"); //orgCode, orgName

  //check if organization name is there from the frontend to save processing time.
  @mutateState()
  createOrgId(orgCode: string, orgName: string): string {
    this.organizations.set(orgCode, orgName);
    return "Organization created with code:" + orgCode + " name: " + orgName;
  }

  getOrgList(): PersistentMap<string, string> {
    return this.organizations;
  }
}

Solution

  • If you want to return a regular map from the contract, you need to parse the map from PersistentMap<string,string> to a regular Map<string,string>. Not only that, but you need to keep track of the keys separately from the map if you want to return all values in addition to the keys. That's because the PersistentMap doesn't store the keys, and you cannot retrieve them (Here's a separate thread about it).

     keys: PersistentVector<string>; // Need to store the keys as well
    
     getOrgList(): Map<string, string> {
        const res: Map<string, string> = new Map<string, string>();
        for (let i = 0; i < this.keys.length; i++) {
          res.set(this.keys[i], this.organizations.getSome(this.keys[i]));
        }
        return res;
     }