diff --git a/posts/2024-04-02-n5-attribute-paths.ipynb b/posts/2024-04-02-n5-attribute-paths.ipynb index 96e2fe1..ff61134 100644 --- a/posts/2024-04-02-n5-attribute-paths.ipynb +++ b/posts/2024-04-02-n5-attribute-paths.ipynb @@ -315,14 +315,6 @@ "Arrays.toString(n5.getAttribute(group, \"array\", String[].class));" ] }, - { - "cell_type": "code", - "execution_count": null, - "id": "760f4b7b", - "metadata": {}, - "outputs": [], - "source": [] - }, { "cell_type": "markdown", "id": "7422f926", @@ -370,7 +362,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "id": "1e7f51b1", "metadata": {}, "outputs": [ @@ -494,7 +486,8 @@ ], "source": [ "n5.setAttribute(group, \"pet\", new Pet(\"Pluto\", 93));\n", - "n5.getAttribute(group, \"pet\", Pet.class);" + "Pet pet = n5.getAttribute(group, \"pet\", Pet.class);\n", + "pet; // without this, it even confused me, making me think that `getAttrbiute` was returing a `String`, not a `Pet`" ] }, { @@ -547,7 +540,8 @@ "source": [ "## Mixing object and array indexing\n", "\n", - "This example sets the value of an integer inside several nested arrays and objects." + "This example sets the value of an integer inside several nested arrays and objects.\n", + "Note: When indexing an array, the path separators `/` at before and after the index operator `[ ]` are optional." ] }, { @@ -571,7 +565,10 @@ "// remove all attributes \n", "n5.removeAttribute(group, \"/\");\n", "\n", + "// Both are equivalent \n", "n5.setAttribute(group, \"one/[2]/three/[4]\", 5);\n", + "n5.setAttribute(group, \"one[2]/three[4]\", 5);\n", + "\n", "n5.getAttribute(group, \"/\", JsonElement.class);" ] }, @@ -582,7 +579,7 @@ "source": [ "## Removing attributes and dealing with nulls\n", "\n", - "We saw about that `removeAttribute` can be used to remove attributes. The first variant takes the group and attribute key as arguments, and returns nothing. The second variant also takes a Class argument and will return an object of type T if possible. If the value of the attribute cannot be parsed into the requested type, the attribute will not be removed, even if the key exists." + "We saw about that `removeAttribute` can be used to remove attributes. The first variant takes the group and attribute key as arguments, and returns nothing after removal. The second variant also takes a Class argument and will return the removed object of type T if possible. If the value of the attribute cannot be parsed into the requested type, the attribute will not be removed, even if the key exists." ] }, { @@ -707,7 +704,7 @@ "id": "241cd1c8", "metadata": {}, "source": [ - "By default, setting the value of an attribute to null will remove that attribute (i.e. the attribute's key will be removed)." + "In the default implemenation, setting the value of an attribute to null will remove that attribute (i.e. the attribute's key will be removed). " ] }, { @@ -791,6 +788,40 @@ "n5WithNulls.getAttribute(group, \"/\", JsonElement.class);" ] }, + { + "cell_type": "markdown", + "id": "94f4cb74", + "metadata": {}, + "source": [ + "While this is the default behaviour, it is strongly recommended to use `removeAttribute` methods when removing attributes, since setting an attribute to `null` it can lead to inconsistent behaviour, depending on how the N5Writer was created. \n", + "Setting an attribute path to `null` can even result in creating attributes along the path, regardless of whether `serializeNulls` is enabled or not. \n", + "\n", + "((Maybe this should move to caveats?))" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "153ae6e1", + "metadata": {}, + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'n5' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[1], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mn5\u001b[49m\u001b[38;5;241m.\u001b[39msetAttribute(group, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124ma/b/c\u001b[39m\u001b[38;5;124m\"\u001b[39m, null)\n", + "\u001b[0;31mNameError\u001b[0m: name 'n5' is not defined" + ] + } + ], + "source": [ + "n5.setAttribute(group, \"a/b/c\", null)\n", + "// I would expect {\"a\":{\"b\":{}}}" + ] + }, { "cell_type": "markdown", "id": "b8b61016", @@ -937,10 +968,27 @@ }, { "cell_type": "markdown", - "id": "f4212a2c", + "id": "df50dfbe", + "metadata": {}, + "source": [ + "## Warnings and caveats\n" + ] + }, + { + "cell_type": "markdown", + "id": "8eb13a15", + "metadata": {}, + "source": [ + "Since keys are paths, when setting a key path where some elements don't exist, it is possible " + ] + }, + { + "cell_type": "markdown", + "id": "2dd9e11a", "metadata": {}, "source": [ - "## Warnings and caveats\n", + "\n", + "\n", "\n", "\n", "::: {.callout-warning}\n", @@ -988,17 +1036,21 @@ "metadata": { "celltoolbar": "Tags", "kernelspec": { - "display_name": "Java", - "language": "java", - "name": "java" + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" }, "language_info": { - "codemirror_mode": "java", - "file_extension": ".jshell", - "mimetype": "text/x-java-source", - "name": "Java", - "pygments_lexer": "java", - "version": "19.0.2+7-Ubuntu-0ubuntu322.04" + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.13" } }, "nbformat": 4,