javascriptjsonminecraft-forge

How can i convert this NBT data string to a valid native javascript object or JSON, and why can the chrome console do it?


So i'm trying to get it so you can export NBT data from minecraft so it can be used in this online tool i'm making. Here is an example of the NBT data I am trying to convert:

const NbtString = "{ForgeCaps:{},Items:[{Count:1b,Slot:0b,id:"the_vault:card",tag:{data:{entries:[{colors:["RED"],groups:["Utility","Stat","Essence"],model:"the_vault:card/icon/mana_regeneration#inventory",modifier:{config:{attribute:"the_vault:mana_regen",maxTier:5b,pool:[{config:'{"min":0.01,"max":0.01,"step":0.01}',tier:1b},{config:'{"min":0.02,"max":0.02,"step":0.01}',tier:2b},{config:'{"min":0.03,"max":0.03,"step":0.01}',tier:3b},{config:'{"min":0.04,"max":0.04,"step":0.01}',tier:4b},{config:'{"min":0.05,"max":0.05,"step":0.01}',tier:5b}]},type:"gear",values:[{tier:1b,value:0.01f},{tier:2b,value:0.02f},{tier:3b,value:0.03f},{tier:4b,value:0.04f},{tier:5b,value:0.05f}]},name:'{"text":"Mana Regeneration Card"}'}],tier:1b}}},{Count:1b,Slot:1b,id:"the_vault:card",tag:{data:{entries:[{colors:["RED","GREEN","BLUE"],groups:["Wild","Stat","Temporal","Resource","Arcane","Evolution"],modifier:{config:{maxTier:1b},type:"dummy"},name:'{"text":"Blue Wild Card"}'}],tier:1b}}},{Count:1b,Slot:2b,id:"the_vault:card",tag:{data:{entries:[{colors:["BLUE"],condition:{config:{tiers:[{pool:[{filters:[{colorFilter:[{value:["GREEN"],weight:1b},{value:["BLUE"],weight:1b},{value:["YELLOW"],weight:1b},{value:["RED"],weight:1b}],groupFilter:[{value:["Stat"],weight:1b},{value:["Resource"],weight:1b},{value:["Evolution"],weight:1b}],minCount:{max:10b,min:7b,type:"uniform"},neighborFilter:[{weight:100b}],tierFilter:[]}],weight:1b},{filters:[{colorFilter:[{value:["GREEN"],weight:1b},{value:["BLUE"],weight:1b},{value:["YELLOW"],weight:1b},{value:["RED"],weight:1b}],groupFilter:[{value:["Stat"],weight:1b},{value:["Resource"],weight:1b},{value:["Evolution"],weight:1b}],minCount:{max:4b,min:3b,type:"uniform"},neighborFilter:[{value:["ROW"],weight:1b},{value:["COLUMN"],weight:1b},{value:["DIAGONAL"],weight:1b},{value:["ADJACENT"],weight:1b}],tierFilter:[]}],weight:1b},{filters:[{colorFilter:[{weight:1b}],groupFilter:[{value:["Arcane"],weight:1b}],maxCount:{max:3b,min:1b,type:"uniform"},neighborFilter:[{weight:1b}],tierFilter:[]}],weight:1b},{filters:[{colorFilter:[{weight:1b}],groupFilter:[{value:["Stat"],weight:1b},{value:["Resource"],weight:1b},{value:["Evolution"],weight:1b}],maxCount:{max:6b,min:4b,type:"uniform"},minCount:{max:2b,min:1b,type:"uniform"},neighborFilter:[{weight:1b}],tierFilter:[]}],weight:1b},{filters:[{colorFilter:[{value:["GREEN"],weight:1b},{value:["BLUE"],weight:1b},{value:["YELLOW"],weight:1b},{value:["RED"],weight:1b}],groupFilter:[{weight:1b}],maxCount:{max:6b,min:4b,type:"uniform"},minCount:{max:2b,min:1b,type:"uniform"},neighborFilter:[{weight:1b}],tierFilter:[]}],weight:1b},{filters:[{colorFilter:[{weight:1b}],groupFilter:[{weight:1b}],maxCount:{max:2b,min:1b,type:"uniform"},neighborFilter:[{value:["ROW"],weight:1b},{value:["COLUMN"],weight:1b},{value:["DIAGONAL"],weight:1b},{value:["ADJACENT"],weight:1b}],tierFilter:[]}],weight:1b}],tier:1b}]},filters:[{tier:1b,value:[{maxCount:1b,neighborFilter:["COLUMN"]}]}]},groups:["Offensive","Arcane"],model:"the_vault:card/icon/ice_blast#inventory",modifier:{config:{attribute:"the_vault:added_ability_level",maxTier:1b,pool:[{config:'{"abilityKey":"Ice_Bolt_Blast","levelChange":1}',tier:1b}]},type:"gear",values:[{tier:1b,value:{ability:"Ice_Bolt_Blast",levelChange:1}}]},name:'{"text":"Glacial Blast Card"}'}],tier:1b}}},{Count:1b,Slot:3b,id:"the_vault:card",tag:{data:{entries:[{colors:["GREEN"],groups:["Utility","Scaling"],model:"the_vault:card/icon/healing_efficiency#inventory",modifier:{config:{attribute:"the_vault:healing_effectiveness",maxTier:5b,pool:[{config:'{"min":0.002,"max":0.002,"step":1.0}',tier:1b},{config:'{"min":0.004,"max":0.004,"step":1.0}',tier:2b},{config:'{"min":0.006,"max":0.006,"step":1.0}',tier:3b},{config:'{"min":0.008,"max":0.008,"step":1.0}',tier:4b},{config:'{"min":0.01,"max":0.01,"step":1.0}',tier:5b}]},type:"gear",values:[{tier:1b,value:0.002f},{tier:2b,value:0.004f},{tier:3b,value:0.006f},{tier:4b,value:0.008f},{tier:5b,value:0.01f}]},name:'{"text":"Scaling Healing Efficiency Card"}',scaler:{config:{tiers:[{pool:[{filters:[{colorFilter:[{value:["GREEN"],weight:1b},{value:["BLUE"],weight:1b},{value:["YELLOW"],weight:1b},{value:["RED"],weight:1b}],groupFilter:[],neighborFilter:[{value:["ROW"],weight:5b},{value:["COLUMN"],weight:5b},{value:["DIAGONAL"],weight:3b},{value:["ADJACENT"],weight:5b},{value:["SURROUNDING"],weight:1b}],tierFilter:[]}],weight:1b},{filters:[{colorFilter:[{value:["GREEN"],weight:1b},{value:["BLUE"],weight:1b},{value:["YELLOW"],weight:1b},{value:["RED"],weight:1b}],groupFilter:[{value:["Stat"],weight:1b},{value:["Evolution"],weight:1b},{value:["Resource"],weight:1b}],neighborFilter:[{value:["ROW"],weight:5b},{value:["COLUMN"],weight:5b},{value:["DIAGONAL"],weight:3b},{value:["ADJACENT"],weight:5b},{value:["SURROUNDING"],weight:1b}],tierFilter:[]}],weight:1b},{filters:[{colorFilter:[],groupFilter:[{value:["Stat"],weight:1b},{value:["Evolution"],weight:1b},{value:["Resource"],weight:1b}],neighborFilter:[{value:["ROW"],weight:5b},{value:["COLUMN"],weight:5b},{value:["DIAGONAL"],weight:3b},{value:["ADJACENT"],weight:5b},{value:["SURROUNDING"],weight:1b}],tierFilter:[]}],weight:1b}],tier:1b}]},filters:[{tier:1b,value:[{colorFilter:["GREEN"],groupFilter:["Evolution"],neighborFilter:["SURROUNDING"]}]}]}}],tier:1b}}},{Count:1b,Slot:4b,id:"the_vault:card",tag:{data:{entries:[{colors:["GREEN"],groups:["Resource"],model:"the_vault:vault_plating#inventory",modifier:{config:{count:[{roll:{max:8b,min:3b,type:"uniform"},tier:1b}],highlightColor:65280,loot:[{item:"the_vault:vault_plating",weight:1.0d}],maxTier:1b,task:"@easy",tooltip:'{"color":"gold","extra":[{"color":"#FFFFFF","text":"${count}"},{"color":"yellow","text":" Vault Plating "},{"text":"${task}"}],"text":"+"}'},counts:[{count:7b,tier:1b}],task:{children:[],config:{filter:"@the_vault:living"},counter:{baseTarget:7b,config:{target:{max:7b,min:6b,type:"uniform"},variables:{targetTierContribution:1b}},current:0b,target:7b,type:"target"},operating:0b,renderer:{tooltip:'{"text":"per ${target} Living Chests looted"}',type:"card"},type:"loot_chest"},type:"task_loot",uuid:[I;-1335797438,959268282,-1831723904,956595013]},name:'{"text":"Vault Plating Card"}'}],tier:1b}}}],id:"quark:variant_chest",x:-317,y:112,z:473}"

That comes straight from Minecrafts "/data get" command.

I've created this function which fixes a lot of things already:

function parseNBT(data) {
    return data
        // Convert "1b", "2b", etc., to plain integers (byte to int)
        .replace(/(\d+)b/g, '$1')

        // Convert "1.0f", "0.2f", etc., to plain numbers (float to number)
        .replace(/(\d*\.?\d+)f/g, '$1')

        // Convert "1.0d", "0.5d" (double) to plain numbers
        .replace(/(\d*\.?\d+)d/g, '$1')

        // Handle "uuid:[I;...]" - Convert to valid JSON array
        .replace(/uuid:\[I;([\d,-]+)\]/g, function (match, p1) {
            return `"uuid": [${p1}]`;
        })
}

I can actually put the string that that function returns inside a variable in the chrome console and the chrome console will parse it as an object.

But within my code i think i can only use JSON.parse and it needs to be formatted as JSON in that case. But that is where things get messy, because of the following reasons:

I've got two questions:

  1. How does the chrome console does it? Is there anyway to do it in the same way the chrome console does it?
  2. If not, can someone help me with how to fix all the issues that arise when trying to format the string to correct JSON?

If you need any more information, please let me know.


Solution

  • How does the chrome console does it? Is there anyway to do it in the same way the chrome console does it?

    The chrome console parses your input as JavaScript rather than JSON, which is less strict and allows e.g. unquoted property names. You can do approximately the same by running:

    eval(`"use strict";(${parseNBT(NBTString)})`)
    

    Be aware of the security implications of eval(): It's a bad idea to use it unless you can trust the source of the NBT string.

    If not, can someone help me with how to fix all the issues that arise when trying to format the string to correct JSON?

    I would recommend going through the many open source NBT parser libraries, and either using one of them directly, or consulting its source code as a reference for your own implementation.