Skip to content

JsonNBT

Electro_593 edited this page Jul 23, 2023 · 1 revision

For anyone who's dealt with loot tables and predicates for long enough, you know the pain of writing SNBT. Single-line, frequent escaping, the nightmare of unmatching brackets... well, no more! Introducing:

JsonNBT

This is a custom format that Spectrum is using to simplify writing NBT in Json files. However, it does have a few constraints, which are noted below. Spectrum also accepts standard SNBT to maintain compatability.

Format

NBTByte

Bytes (8-bit signed values) are represented as Json strings, with the format "[0-9]+[bB]". Additionally, the boolean values true and false map to 1b and 0b, respectively. For example:

{
  "NBTBytes": [
    "127b",
    "-128B",
    true,
    false
  ]
}

NBTShort

Shorts (16-bit signed values) are represented as Json strings, with the format "[0-9]+[sS]". For example:

{
  "NBTShorts": [
    "32767s",
    "-32768S"
  ]
}

NBTInt

Integers (32-bit signed values) are represented as Json numbers, with the format [0-9]+. As mentioned in Limitations, decimal points are also valid as long as the number is whole. Additionally, to help with specificity, JsonNBT interprets "[0-9]+[iI]" as integers as well. For example:

{
  "NBTInts": [
    "2147483647i",
    "-2147483648I",
    12,
    -3.00
  ]
}

NBTLong

Longs (64-bit signed values) are represented as Json strings, with the format "[0-9]+[lL]". For example:

{
  "NBTLongs": [
    "9223372036854775807l",
    "-9223372036854775808L"
  ]
}

NBTFloat

Floats (32-bit floating-point values) are represented as Json strings, with the suffix f or F. For example:

{
  "NBTFloats": [
    "3.40282346639e+38f",
    "-3.40282346639E+38F"
  ]
}

NBTDouble

Doubles (64-bit floating-point values) are represented as Json strings, with the suffix d or D. Additionally, Json numbers that have a fractional component or are larger than an integer will be parsed as a double. For example:

{
  "NBTDoubles": [
    "1.7976931348623157e+308d",
    "-1.7976931348623157E+308D",
    0.5,
    1000000000000
  ]
}

NBTString

Strings are represented as Json strings, when none of the other formats apply. For example:

{
  "NBTStrings": [
    "Hello, world!",
    "This is a string"
  ]
}

NBTList

Lists are represented as Json arrays. Note that each element in the array must be parsed to the same NBT type. For example:

{
  "NBTList": [
    "1b",
    "2b",
    true
  ]
}

NBTCompound

Compounds are represented as Json objects. The only difference from SNBT is that the keys are quoted. For example:

{
  "NBTCompound": {
    "key1": "value1",
    "key2": "value2"
  }
}

NBTByteArray

Byte arrays are the same as a list of bytes, but with the first element being "B;". For example:

{
  "NBTByteArray": [
    "B;",
    "1b",
    "2b",
    true
  ]
}

NBTIntArray

Int arrays are the same as a list of integers, but with the first element being "I;". For example:

{
  "NBTIntArray": [
    "I;",
    30,
    171,
    -10
  ]
}

NBTLongArray

Long arrays are the same as a list of longs, but with the first element being "L;". For example:

{
  "NBTLongArray": [
    "L;",
    "12135L",
    "-43L"
  ]
}

Limitations

Unfortunately, since Json is less specific than SNBT, this format is not without its limitations. Specifically, since strings are being used to add type information, it's possible that a string may be interpreted as a number even when you don't want it to. Of course, it's unlikely that you'll be using strings such as "B;" and "13d", and we still support standard SNBT in that case.

Another limitation is that some NBT contains Json within itself (e.g. CustomName), which currently must be expressed in a string. We may revisit this in the future, but for now, the complexity isn't worth it.

Also, since Json doesn't differentiate between integers and floating-point numbers, there isn't a good way to handle plain numbers. We currently just check if it can fit into an integer, so both 123 and 1.0 are integers, but 0.5 and 1000000000000 are doubles. If your number is ambiguous, you can specify its type explicitly via a string with the i/I and d/D suffixes.

Suggestions

If you have any suggestions, please feel free to mention them! This format is meant to simplify things in Minecraft's increasingly data-driven model, so any feedback is appreciated.

Clone this wiki locally