Skip to content
Andre Issa edited this page Dec 18, 2021 · 25 revisions
SJSON Structure
Mirroring Structure
Keywords

SJSON Structure

Here's official documentation on the structure of SJSON (Simplified JSON)

Mirroring Structure

To make only the changes you want to make to an sjson file, the sjson file to be merged must be constructed so it 'mirrors' the structure of the original file.

This means that say you want to change a particular value, you must also construct all of the sequences and objects this value is contained within, but you only need to contain the particular keys and indices that eventually contains the value you want to change.

For all the following, let's say this is the original sjson file we want to modify

{
  Sequence = [
    102
    250
    {
      OtherKey = 45
      MyKey = "value"
      AnotherKey = 20
    }
    -30.5
  ]
}

We have to be careful about sequences (like lua tables with no keys which implictly have numeric keys), but objects are relatively simple (think of lua tables with explicit keys).
For objects we merely have to write an object that contains the key and value we want, but for sequences we probably do not want to overwrite everything that comes before a certain index, so we have to use keywords.

So to change the value at MyKey to "newvalue", this is the corresponding merge sjson

{
  Sequence = {
    "_sequence" = true
    3 = {
      MyKey = "newvalue"
    }
  }
}

Notice that { and } are used instead of [ and ].
This is because the importer will convert this object that contains the keyword "_sequence" into a sequence.
The sequence it is converted into contains 'non existent' entries to pad out the indices not specified, this way it will not affect any values before the index you wanted to change.

Many sequences can be extended to contain more of the same kinds of values and will be loaded into game like that, so we will also want to be able to add new entries to a sequence without having to know exactly how long the sequence is ahead of time, for this we can use the "_append" keyword, and this time we do not need to use an object to generate the sequence.

{
  Sequence = [
    "_append"
    "newvalue"
  ]
}

This adds the entry "newvalue" to the end of Sequence in the original file

If we want to replace a value, the only time this may be a problem is when the values are the same type and are both containers (sequences or objects).
To prevent merging the containers, add the "_replace" keyword to it.
Instead of merging the keys and sub-keys and so forth, it will completely replace the original container.

{
  Sequence = {
    "_sequence" = true
    3 = {
      "_replace" = 1
      MyKey = "newvalue"
    }
  }
}

This will end up effectively deleting the keys OtherKey and AnotherKey because they were not contained in the object we are replacing it with.

{
  Sequence = [
    "_replace"
    "newvalue"
  ]
}

This replaces the entire Sequence sequence with a sequence that only contains "newvalue".

If we want to remove an index or key entirely, we cannot just set it to nil like we can in lua.
You could replace the object it is contained within, but that can be dangerous and tedious if you only want to remove a few things and in different places.
Instead we have to set it to the "_delete" keyword

{
  Sequence = {
    "_sequence" = true
    3 = {
      MyKey = "_delete"
    }
  }
}

This will delete MyKey only

Keywords

General keywords are the entire values:

  • "_delete" Removes the (key at the) position mirrored in the original file

Sequences

Sequences are marked by brackets ([ and ])
Sequence keywords are the values of the first entry:

  • "_append"
    Adds all its entries to the end of the sequence mirrored in the original file (if it is a sequence)
  • "_replace" Replaces the container mirrored in the original file with itself (not including the keyword)

Dictionaries

Dictionaries are marked by braces ({ and })
Dictionary keywords are keys with truthy values:

  • "_sequence"
    Ignores all keys that are not stringified positive integers.
    Keys that are positive integers are mapped to the entry at the integer value of the key in the sequence mirrored in the original file
  • "_replace" Replaces the container mirrored in the original file with itself (not including the keyword)