Search code examples
javajsontostringjson-simple

JSON custumize toString


You can answer the entire question with only reading my question in BOLD letters below, I wanted to provide some context just in case the question is not clear

I am recreating a blockchain and therefore need to verify that the blocks created fullfill a given requirement (hashing the entire block (where the miner put in his nonce solution) has to be smaller than a given target).

So what I am currently doing and what is working is:

private static boolean checkDifficulty(JSONObject message) {
try {
        String blockString = message.get("block").toString();
        JSONObject blockPayLoad = (JSONObject) JSONValue.parse(blockString);
        BlockPayload block = new BlockPayload(blockPayLoad);
        BigInteger base = new BigInteger("2",16);
        String difficulty = Integer.toHexString(20+block.getDifficulty());
        BigInteger exponent = new BigInteger(difficulty,16);
        BigInteger totalSpace = base.pow(512);
        BigInteger target = totalSpace.divide(base.pow(exponent.intValueExact()));
        BigInteger hashedBlock3 = new BigInteger(1,hashSHA512(blockString));
return(hashedBlock3.compareTo(target) == -1);

    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }

    return false;

What I first thought I could do though, that I use my datastrucutre BlockPayload. The relevant part looks like this:

public BlockPayload(JSONObject blockPayLoad) {
    this.stringRepresentation = blockPayLoad.toString();
    this.type = blockPayLoad.get("type").toString();        
    this.transactions = blockPayLoad.get("transactions").toString();        
    this.timestamp = blockPayLoad.get("timestamp").toString();
    this.reward = blockPayLoad.get("reward").toString();
    this.difficulty = Integer.parseInt(blockPayLoad.get("difficulty").toString());
    this.nonce = blockPayLoad.get("nonce").toString();
    this.parent = blockPayLoad.get("parent").toString();
}

my toString() returns the stringReprensentation. Sadly, trying the same thing above (hashing the String reprensentation) yields a different result.

I figured that this is b/c my toString does not have the same order, meaning that the attributes' order within the JSONObject is changed.

So here is my question: Can I customize the toString() in a way, that i guarantee the attributes are shown in the wanted order?


Solution

  • Yep you can put them in a treemap then you can hash them,tree map is a completely ordered map without do anything it is ordering the elements by keys from the lower to the higher take a look at https://beginnersbook.com/2013/12/treemap-in-java-with-example/

    TreeMap<String, String> tmap = 
             new TreeMap<String, String>();
     tmap.put("1", "Data1");
      tmap.put("23", "Data2");
      tmap.put("70", "Data3");
      tmap.put("4", "Data4");
      tmap.put("2", "Data5");
    // this will be like this after converting it to Json using Gson lib
    // new Gson ().toJson(tmap);
    {"1":"Data1","2":"Data5","23":"data2","4":"data4","70":"Data3"}