Would someone give a thorough explanation of 1.14 Minecraft's /data modify?

Okay, so I've been searching all over the internet for an explanation of data modify ever since I heard Sethbling passively mention it in one of his videos. The only thing I could find on it was the wiki and the update log for the 1.14 snapshot. So, I checked these, and they hardly explained it at all. I can get /data modify block 123 20 123... and that's as far as I get.

Minecraft wiki does not at all define clearly what is (the thing meant to go after coords), nor does it specify what each operation does to what. Operations include (without explanation, and excluding set (which it does explain)): append, insert, merge, and prepend. Then, it has from|value as the next option, which aren't explained either. After this, it just has block/entity and coords/id. So, I know the format (mostly), but I haven't the slightest idea what any of it means. And nothing I've seen on the internet even mentions the command save for Minecraft wiki itself.

Please explain if you know what data modify is. Thanks!


This answer not only describes /data modify, but also NBT paths, branching NBT paths and NBT in JSON, because these features are all linked and to understand any of them fully, you need to at least know a bit about the others.


The first big advantage of /data modify is that you can edit NBT without completely overwriting it. For example I used it in this answer to modify only one specific number of a trade of a villager (or actually all trades, because 1.14 also adds the ability to do things with multiple NBT paths at once):

/data modify entity <selector> Offers.Recipes[].maxUses set value 1000000

This command changes only the maxUses tag of the trade, unlike /data merge, which requires you to write the entire trade new.

The second big advantage is that you can copy entire NBT compounds from one location to another. In this answer one of the steps is to copy item data from one chest to another:

/data modify block 0 0 0 Items append from block 12 34 56 Items[{Slot:4b}]

This command copies the NBT data from slot 4 of a chest at coordinates 12 34 56 to slot 4 of a chest at 0 0 0, including the count, all item tags and so on.

The third big advantage is that you can do basic string manipulation, for example you can copy strings from one location in NBT to another. An example is at the end of this answer.


Now a more formal definition:

/data modify block <pos>

This modifies the NBT of a block at coordinates <pos>, for example 0 0 0.

/data modify entity <target>

This modifies the NBT of an entity selected with <target>, for example @e[type=item,sort=nearest,limit=1]. This selector only allows one entity for reasons I don't know. It's not enough that the selector happens to just match one entity, you have to explicitly use @p, @r, @s or limit=1. You can still use it for multiple entities with execute as <selector> run data modify entity @s.

/data modify (block <pos>|entity <target>) <path>

This <path> is an NBT path like Offers.Recipes[0].maxUses, which makes the command only operate on that path, without affecting anything above, like Offers.Recipes[1].rewardExp. The syntax is also not explained well in the wiki, so here's a quick summary. Skip to the next separator line if you already know everything about NBT paths, even in 1.14.


/data get block 0 0 0 without a path prints to chat all the NBT data of the block entity of a container at coordinates 0 0 0, for example:

{x:0,y:0,z:0,id:"minecraft:chest",Items:[{Slot:0b,id:"minecraft:stone",Count:1b}]}

data get block 0 0 0 Items prints only the NBT compound Items, if it exists (I won't list all the possible errors here):

[{Slot:0b,id:"minecraft:stone",Count:1b}]

The return value (used mainly in /execute store result) of this is the length of the compound or list, for example in this case it would be 1, because there is only 1 stack of items in the chest. This command returns 3 and prints the first element of the list of items to chat (because lists are 0-indexed, they count "0, 1, 2, 3, …"): /data get block 0 0 0 Items[0]

{Slot:0b,id:"minecraft:stone",Count:1b}

You can go deeper with periods: /data get block 0 0 0 Items[0].Count:

1b

In theory you could also put two list indices in a row, like foo.bar[0][0].lalala to get the lalala tag in the first element of the first element of the bar list in the foo tag, but as far as I know, no Vanilla entities or block entities use lists directly in lists.

And now the fancy 1.14 bits:

You can use NBT in JSON now, like this:

/tellraw @s {"nbt":"Inventory","entity":"@s"}

This tells yourself your own inventory.

You can then also get a JSON list of all individual slots:

/tellraw @s {"nbt":"Inventory[]","entity":"@s"}

So far this is pretty useless, because it's just differently formatted, but there are useful examples for this (one is my villager answer) and you can also filter, like this:

/tellraw @s {"nbt":"Inventory[{id:\"minecraft:stone\"}]","entity":"@s"}

This prints a list of all slots that contain stones.


Back to /data modify:

/data modify (block <pos>|entity <target>) <path> set

The simplest case, similar to /data merge, except that it only operates on the specified path.

/data modify (block <pos>|entity <target>) <path> merge

Very similar to set, except that it does not delete things that you don't specify. Example:

/data modify block <pos> Items[0] merge value {tag:{display:{Name:"{\"text\":\"Test\"}"}}}

This renames the first item in the container at those coordinates to "Test", without affecting its type, count or position in the container. set would try to replace the first item entirely with one that only has a tag tag, which doesn't work, so it deletes it. I'm sure there are good uses for set as well.

/data modify (block <pos>|entity <target>) <path> append

This one adds an element to an existing list, for example you could give a villager an additional trade. Specifically, this adds it to the end of the list, which matters for villager trades, the arrangement of passengers, banner patterns, lore lines, book pages and probably more.

/data modify (block <pos>|entity <target>) <path> prepend

Same as append, but it adds to the beginning of the list.

/data modify (block <pos>|entity <target>) <path> insert <index>

This inserts an additional element into a list at a specified index. All items that had this or a higher index before will get shifted to have an index that is 1 higher. So for example insert 2 value 42 would change a list like "0,1,2,3,4,5" to "0,1,42,2,3,4,5", because you added 42 in position 2 (again 0-indexed) and moved everything else to the right.

/data modify (block <pos>|entity <target>) <path> (set|merge|append|prepend|insert <index>) value <value>

Here you can specify exact NBT, for example to set the maxUses tag of a villager's first trade to 1000, you would use this command:

/data modify entity @e[type=villager,sort=nearest,limit=1] Offers.Recipes[0].maxUses set value 1000

Or to overwrite the entire first trade, you do this:

/data modify entity @e[type=villager,sort=nearest,limit=1] Offers.Recipes[0] set value {buy:{id:"stone",Count:1},sell:{id:"diamond_block",Count:64},maxUses:1000}

And now the second big advantage, copying NBT:

/data modify (block <pos1>|entity <target>) <path> (set|merge|append|prepend|insert <index>) from (block <pos2>|entity <target>) <path>

This copies the selected NBT element to the other location. Example:

/data modify block <pos1> Items set from block <pos2> Items

This makes one container a copy of another. Another example, these this command copies the custom name from the closest villager to the closest cow:

/data modify entity @e[type=cow,sort=nearest,limit=1] CustomName set from entity @e[type=villager,sort=nearest,limit=1] CustomName

This basic string manipulation was previously impossible, because you couldn't do anything with strings other than setting it or checking for exact values. Now you can also compare two strings, by first copying one of them somewhere, then trying to copy the other to the same target. If the success value of the second command is 1, then the second command wrote something different to the target than the first one, so the two strings are not the same.


Thanks to the Minecraft developers Slicedlime on YouTube and Boq on Discord who cleared up the difference between /data modify … set and /data modify … merge! Minecraft wiki user Liachmodded has created a first draft of a new wiki page layout for the /data command based on this answer, so you can see it in a tree view: https://minecraft.gamepedia.com/User:Liachmodded/TreeCommandWIP

P.S.: Did you know that negative list indices work now? /data get entity @s Inventory[-1] prints the item in the last filled slot from your inventory to chat and /data modify entity @e[type=villager,sort=nearest,limit=1] Offers.Recipes insert -3 value {buy:{id:"stone",Count:1},sell:{id:"diamond_block",Count:64},maxUses:1000} adds an additional villager trade before the last two existing ones.