2

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;
  }
}
MSaudi
  • 4,442
  • 2
  • 40
  • 65
  • 1
    Does the same error happen if you remove the backslahes from postData? And do you use @nearBingden annotation on the contract? – John Feb 11 '22 at 13:03
  • @John I added the full contract code. It does not accept it when I remove the backslashes – MSaudi Feb 11 '22 at 13:11
  • @John update: I changed the command-line interface to use git bash and data got sent -without the backslashes- and there is no crash now. But still don't see the data returned. – MSaudi Feb 11 '22 at 13:19
  • 1
    @John I have a great update. removing the backslashes seems to work. No crashes now and when I return 1 element, I'm able to see it. The problem now is that returning the map does not print the elements but prints { _elementPrefix: 'oc::' } – MSaudi Feb 11 '22 at 13:22

1 Answers1

0

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;
 }
John
  • 10,165
  • 5
  • 55
  • 71
  • I'm wondering if there is a million record, will the function execute within the 200ms limit? also is uding a Map instead of PersistsanceMap a good call in this scenario ? – MSaudi Feb 11 '22 at 14:00
  • 1
    I'm not sure about the performance of this. Maybe it's better to have some kind of pagination system in place. – John Feb 11 '22 at 14:37
  • Thanks for your support, John. – MSaudi Feb 11 '22 at 16:37