<br />
<b>Warning</b>:  The magic method SFML_Singleton::__wakeup() must have public visibility in <b>/home/public/wp-content/plugins/sf-move-login/inc/classes/class-sfml-singleton.php</b> on line <b>72</b><br />
{"id":239,"date":"2018-04-30T09:20:23","date_gmt":"2018-04-30T15:20:23","guid":{"rendered":"http:\/\/www.munderwood.ca\/?p=239"},"modified":"2018-04-30T09:20:23","modified_gmt":"2018-04-30T15:20:23","slug":"what-to-do-if-js-data-serializes-array-elements-as-empty-objects","status":"publish","type":"post","link":"https:\/\/www.munderwood.ca\/index.php\/2018\/04\/30\/what-to-do-if-js-data-serializes-array-elements-as-empty-objects\/","title":{"rendered":"What to do if js-data serializes array elements as empty objects"},"content":{"rendered":"<p style=\"padding-left: 30px;\"><em>TL;DR: Use the <a href=\"http:\/\/api.js-data.io\/js-data\/3.0.1\/Schema.html#toc6__anchor\"><span class=\"lang:default decode:true crayon-inline\">items<\/span> validation keyword<\/a>\u00a0to specify the data type of the elements of arrays in your js-data schema to avoid unexpected results when serializing records, e.g. for saving.<\/em><\/p>\n<h2>The setup<\/h2>\n<p>I was using <a href=\"http:\/\/www.js-data.io\/\">js-data v3<\/a> with a schema containing an array field recently, and came across some initially baffling behaviour. I had a <span class=\"lang:default decode:true crayon-inline \">fooSchema<\/span> that included a field definition along these lines:<\/p>\n<pre class=\"lang:js decode:true\" title=\"Troublesome array field definition\">import { Schema } from 'js-data';\r\n\r\nconst FooSchema = new Schema({\r\n  \/\/ ...\r\n  barIds: {\r\n    type: 'array',\r\n  },\r\n  \/\/ ...\r\n});\r\n\r\n<\/pre>\n<p>A\u00a0<span class=\"lang:default decode:true crayon-inline \">Foo<\/span>\u00a0object could have many associated <span class=\"lang:default decode:true crayon-inline \">Bar<\/span>\u00a0objects, and the API supplying the data specified them by including an array of their integer ids in the <span class=\"lang:default decode:true crayon-inline \">barIds<\/span>\u00a0field. Simple enough, and the above worked perfectly while consuming the output of the API. The unexpected behaviour didn&#8217;t start until I tried to send the array back to the API to update the record.<\/p>\n<h2>Serializing the array<\/h2>\n<p>When calling the <span class=\"lang:js decode:true crayon-inline\">save<\/span>\u00a0method on a <span class=\"lang:default decode:true crayon-inline \">Record<\/span>\u00a0, the defined\u00a0<span class=\"lang:default decode:true crayon-inline\">Mapper<\/span>\u00a0serializes it with the <span class=\"lang:default decode:true crayon-inline\">toJSON<\/span>\u00a0method. Given the above schema, a record with\u00a0<span class=\"lang:default decode:true crayon-inline \">barIds === [2, 3, 5]<\/span>\u00a0 was getting converted to the JSON field\u00a0<span class=\"lang:js decode:true crayon-inline\">barIds: [{}, {}, {}]<\/span>. The length of the JSON array was always equal to the length of the underlying data array, but it never contained anything except empty objects instead of the desired relationship information.<\/p>\n<h2>A simple solution<\/h2>\n<p>When an array field in a record with a schema is serialized by js-data, each element is mapped to an empty object unless a valid <a href=\"http:\/\/json-schema.org\/\">JSON Schema<\/a> for the <em>element<\/em> is specified. This choice of defaulting to\u00a0<span class=\"lang:default decode:true crayon-inline \">{}<\/span>\u00a0happens in the <a href=\"https:\/\/github.com\/js-data\/js-data\/blob\/master\/src\/Schema.js#L1218\">Schema#pick method<\/a>, when the <span class=\"lang:default decode:true crayon-inline\">type<\/span>\u00a0 property of the schema is\u00a0<span class=\"lang:default decode:true crayon-inline\">&#8216;array&#8217;<\/span>. To prevent this, simply specify the expected schema for the array elements in the schema for the records. In my case since the ids are numbers, this meant:<\/p>\n<pre class=\"lang:js mark:7 decode:true\" title=\"Working array field definition\">import { Schema } from 'js-data';\r\n\r\nconst FooSchema = new Schema({\r\n  \/\/ ...\r\n  barIds: {\r\n    type: 'array',\r\n    items: { type: 'number' },\r\n  },\r\n  \/\/ ...\r\n});<\/pre>\n<p>The <a href=\"http:\/\/api.js-data.io\/js-data\/3.0.1\/Schema.html#toc6__anchor\"><span class=\"lang:default decode:true crayon-inline\">items<\/span>\u00a0validation keyword<\/a>\u00a0specifies how the elements of an array-type property should be treated. If not specified, the default is to treat them as objects. If the array contains actual related elements, then a js-data schema could be given, for example\u00a0<span class=\"lang:js decode:true crayon-inline \">bars: BarSchema<\/span>. Otherwise, any valid JSON Schema definition should provide the desired results.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>TL;DR: Use the items validation keyword\u00a0to specify the data type of the elements of arrays in your js-data schema to avoid unexpected results when serializing records, e.g. for saving. The setup I was using js-data v3 with a schema containing an array field recently, and came across some initially baffling behaviour. I had a fooSchema &#8230; <span class=\"more\"><a class=\"more-link\" href=\"https:\/\/www.munderwood.ca\/index.php\/2018\/04\/30\/what-to-do-if-js-data-serializes-array-elements-as-empty-objects\/\">[Read more&#8230;]<\/a><\/span><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[3],"tags":[17],"_links":{"self":[{"href":"https:\/\/www.munderwood.ca\/index.php\/wp-json\/wp\/v2\/posts\/239"}],"collection":[{"href":"https:\/\/www.munderwood.ca\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.munderwood.ca\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.munderwood.ca\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.munderwood.ca\/index.php\/wp-json\/wp\/v2\/comments?post=239"}],"version-history":[{"count":10,"href":"https:\/\/www.munderwood.ca\/index.php\/wp-json\/wp\/v2\/posts\/239\/revisions"}],"predecessor-version":[{"id":249,"href":"https:\/\/www.munderwood.ca\/index.php\/wp-json\/wp\/v2\/posts\/239\/revisions\/249"}],"wp:attachment":[{"href":"https:\/\/www.munderwood.ca\/index.php\/wp-json\/wp\/v2\/media?parent=239"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.munderwood.ca\/index.php\/wp-json\/wp\/v2\/categories?post=239"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.munderwood.ca\/index.php\/wp-json\/wp\/v2\/tags?post=239"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}