{"id":16998675,"url":"https://github.com/joht/data-restructor-js","last_synced_at":"2026-02-01T11:12:47.327Z","repository":{"id":37012797,"uuid":"307053933","full_name":"JohT/data-restructor-js","owner":"JohT","description":"Transforms parsed JSON objects into a uniform data structure","archived":false,"fork":false,"pushed_at":"2024-05-22T15:59:44.000Z","size":4250,"stargazers_count":2,"open_issues_count":4,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-05-22T17:02:56.998Z","etag":null,"topics":["adapter","data-structures","javascript","json","parser","restructure"],"latest_commit_sha":null,"homepage":"https://joht.github.io/data-restructor-js/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/JohT.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-10-25T08:20:39.000Z","updated_at":"2024-05-31T22:36:55.166Z","dependencies_parsed_at":"2023-12-02T05:22:48.081Z","dependency_job_id":"7a77d67d-8ad9-4585-83ea-4b7252a1ae58","html_url":"https://github.com/JohT/data-restructor-js","commit_stats":{"total_commits":313,"total_committers":5,"mean_commits":62.6,"dds":0.6869009584664536,"last_synced_commit":"bfef7007c3e955555e567a5e6ba2f81f618dd7e6"},"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JohT%2Fdata-restructor-js","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JohT%2Fdata-restructor-js/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JohT%2Fdata-restructor-js/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JohT%2Fdata-restructor-js/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/JohT","download_url":"https://codeload.github.com/JohT/data-restructor-js/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244978584,"owners_count":20541879,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["adapter","data-structures","javascript","json","parser","restructure"],"created_at":"2024-10-14T04:05:52.452Z","updated_at":"2025-03-22T15:31:10.436Z","avatar_url":"https://github.com/JohT.png","language":"JavaScript","readme":"# data-restructor-js\n\n[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)\n![Language](https://img.shields.io/github/languages/top/JohT/data-restructor-js)\n![Branches](https://img.shields.io/badge/branches-94.61%25-brightgreen.svg?style=flat)\n![![npm](./src/npm.svg)](https://aleen42.github.io/badges/src/npm.svg)\n![![jasmine](./src/jasmine.svg)](https://aleen42.github.io/badges/src/jasmine.svg)\n![![eslint](./src/eslint.svg)](https://aleen42.github.io/badges/src/eslint.svg)\n![JSDoc](https://img.shields.io/github/package-json/dependency-version/JohT/data-restructor-js/dev/jsdoc)\n![nyc](https://img.shields.io/github/package-json/dependency-version/JohT/data-restructor-js/dev/nyc)\n![parcel-bundler](https://img.shields.io/github/package-json/dependency-version/JohT/data-restructor-js/dev/parcel)\n\nWhen parsing JSON on client-side, the structure of it attracts most of our attention.  \nIf the structure evolves over time, it leads to recurring changes in the code that depends on it.\n\n## Features\n\n- Adapter that takes e.g. parsed JSON and transforms it into a uniform structure\n- Multiple transformation steps including flattening, removing duplicates, grouping, ...\n- Takes descriptions that reflect the incoming structure and define the uniform output\n- Reusable and flexible\n- Supports most browser including IE 5\n\n## Not intended to be used when\n\n- a \"backend for frontend\" exists, that is responsible for delivering the structure and content the way the client needs it.\n- the structure of the data is already stable, well abstracted and/or rather generic.\n- the code, that depends on the structure of the data, can easily be changed (only a view lines, same team, ...).\n\n## Quickstart\n\nUse the following command to install the library using npm:\n\n```shell\nnpm install data-restructor\n```\n\nAlternatively, the sources can be found inside the\n[source folder](https://github.com/JohT/data-restructor-js/tree/master/src/):\n\n- [datarestructor.js](https://github.com/JohT/data-restructor-js/blob/master/src/js/datarestructor.js)\n- [templateResolver.js](https://github.com/JohT/data-restructor-js/blob/master/src/js/templateResolver.js)\n- [describedfield.js](https://github.com/JohT/data-restructor-js/blob/master/src/js/describedfield.js)\n\nThe development artifacts (not minified) can be found inside the\n[devdist folder](https://github.com/JohT/data-restructor-js/tree/master/devdist):\n\n- [datarestructor-ie-global-all.js](https://github.com/JohT/data-restructor-js/blob/master/devdist/datarestructor-ie-global-all.js) all sources including polyfills merged to be used without module system\n- [datarestructor-global-all.js](https://github.com/JohT/data-restructor-js/blob/master/devdist/datarestructor-global-all.js) all sources without polyfills merged to be used without module system\n- [datarestructor.js](https://github.com/JohT/data-restructor-js/blob/master/devdist/datarestructor.js)\n- [templateResolver.js](https://github.com/JohT/data-restructor-js/blob/master/devdist/templateResolver.js)\n- [describedfield.js](https://github.com/JohT/data-restructor-js/blob/master/devdist/describedfield.js)\n\nHere are some code examples on how these modules can be imported:\n\n```javascript\nvar template_resolver = template_resolver || require(\"data-restructor/devdist/templateResolver\"); // supports vanilla js\nvar described_field = described_field || require(\"data-restructor/devdist/describedfield\"); // supports vanilla js\nvar datarestructor = datarestructor || require(\"data-restructor/devdist/datarestructor\"); // supports vanilla js\n```\n\nThe built (minified) versions can be found inside the\n[distribution folder](https://github.com/JohT/data-restructor-js/tree/master/dist):\n\n- [datarestructor-ie-global-all-min.js](https://github.com/JohT/data-restructor-js/blob/master/dist/datarestructor-ie-global-all-min.js) all sources including polyfills merged and minified to be used without module system\n- [datarestructor-global-all-min.js](https://github.com/JohT/data-restructor-js/blob/master/dist/datarestructor-global-all-min.js) all sources without polyfills merged and minified to be used without module system\n- [datarestructor.js](https://github.com/JohT/data-restructor-js/blob/master/dist/datarestructor.js)\n- [datarestructor-ie.js](https://github.com/JohT/data-restructor-js/blob/master/dist/datarestructor-ie.js) (full compatibility with IE)\n- [templateResolver.js](https://github.com/JohT/data-restructor-js/blob/master/dist/templateResolver.js)\n- [templateResolver-ie.js](https://github.com/JohT/data-restructor-js/blob/master/dist/templateResolver-ie.js) (full compatibility with IE)\n- [describedfield.js](https://github.com/JohT/data-restructor-js/blob/master/dist/describedfield.js)\n- [describedfield-ie.js](https://github.com/JohT/data-restructor-js/blob/master/dist/describedfield-ie.js) (full compatibility with IE)\n\n## Code Documentation\n\nThe [code documentation](https://joht.github.io/data-restructor-js) is generated using [JSDoc](https://jsdoc.app) and is published using [GitHub Pages](https://pages.github.com) at [https://joht.github.io/data-restructor-js](https://joht.github.io/data-restructor-js).\n\n## Build all\n\nUse the following [commands](COMMANDS.md) to build and package the module. A list of all commands can be found in [COMMANDS.md](COMMANDS.md).\n\n```shell\nnpm install merger-js -g\nnpm install\nnpm run package\n```\n\n**Note:** merger.js prompts to select a source file. Please select \"ALL\" using the arrow keys and press enter to continue.\n\n## Example\n\nAs a starting point you may have a look at the following example.  \nA running, comprehensive example can be found here:\n[DataRestructorUseCaseTest.js](https://github.com/JohT/data-restructor-js/blob/master/test/js/DataRestructorUseCaseTest.js)\n\n### Input Object\n\n```json\n{\n    \"responses\": [\n        {\n            \"hits\": {\n                \"total\": {\n                    \"value\": 1\n                },\n                \"hits\": [\n                    {\n                        \"_source\": {\n                            \"iban\": \"AT424321012345678901\",\n                            \"accountnumber\": \"12345678901\",\n                            \"customernumber\": \"00001234567\",\n                            \"currency\": \"USD\",\n                            \"tags\": [\n                                \"active\",\n                                \"online\"\n                            ]\n                        }\n                    }\n                ]\n            }\n        }\n    ]\n}\n```\n\n### Code\n\n```javascript\nfunction restructureJson(jsonData) {\n  var allDescriptions = [];\n  allDescriptions.push(summariesDescription());\n  allDescriptions.push(detailsDescription());\n  return new datarestructor.Transform(allDescriptions).processJson(jsonData);\n}\n\nfunction summariesDescription() {\n  return new datarestructor.PropertyStructureDescriptionBuilder()\n    .type(\"summary\")\n    .category(\"account\")\n    .propertyPatternEqualMode()\n    .propertyPattern(\"responses.hits.hits._source.accountnumber\")\n    .groupName(\"summaries\")\n    .groupPattern(\"{{category}}--{{type}}--{{index[0]}}--{{index[1]}}\")\n    .build();\n}\n\nfunction detailsDescription() {\n  return new datarestructor.PropertyStructureDescriptionBuilder()\n    .type(\"detail\")\n    .category(\"account\")\n    .propertyPatternTemplateMode()\n    .propertyPattern(\"responses.hits.hits._source.{{fieldName}}\")\n    .groupName(\"details\")\n    .groupPattern(\"{{category}}--{{type}}--{{index[0]}}--{{index[1]}}\")\n    .groupDestinationPattern(\"account--summary--{{index[0]}}--{{index[1]}}\")\n    .build();\n  }\n```\n\n### Output Java Object\n\nAn Javascript object with mainly this structure (see [DescribedEntry](#describedentry) for more details) and content is returned, when the function `restructureJson` from above is called:\n\n```yaml\ncategory: \"account\"\ndisplayName: \"Accountnumber\"\nfieldName: \"accountnumber\"\ntype: \"summary\"\nvalue: \"12345678901\"\ndetails:\n  - category: \"account\"\n    type: \"detail\"  \n    displayName: \"Iban\"\n    fieldName: \"iban\"\n    value: \"AT424321012345678901\"\n  - category: \"account\"\n    type: \"detail\"\n    displayName: \"Accountnumber\"\n    fieldName: \"accountnumber\"\n    value: \"12345678901\"\n  - category: \"Konto\"\n    type: \"detail\"\n    displayName: \"Customernumber\"\n    fieldName: \"customernumber\"\n    value: \"00001234567\"\n  - category: \"Konto\"\n    type: \"detail\"\n    displayName: \"Currency\"\n    fieldName: \"currency\"\n    value: \"USD\"\n  - category: \"Konto\"\n    type: \"detail\"\n    displayName: \"Tags\"\n    fieldName: \"tags\"\n    value: \"active\"\n  - category: \"Konto\"\n    type: \"detail\"\n    displayName: \"Tags\"\n    fieldName: \"tags\"\n    value: \"online\"\n  - category: \"Konto\"\n    type: \"detail\"\n    displayName: \"Tags\"\n    fieldName: \"tags_comma_separated_values\"\n    value: \"active, online\"\n```\n\n## Transformation Steps\n\n### 1. Flatten hierarchical data object\n\nThe input data object, e.g. parsed from JSON, is converted to an array of point separated property names and their values.\nFor example this structure...\n\n```json\n{\n    \"responses\": [\n        {\n            \"hits\": {\n                \"total\": {\n                    \"value\": 1\n                },\n                \"hits\": [\n                    {\n                        \"_source\": {\n                            \"accountnumber\": \"123\"\n                        }\n                    }\n                ]\n            }\n        }\n    ]\n}\n```\n\n...is flattened to...\n\n```javascript\nresponses[0].hits.total.value=1\nresponses[0].hits.hits[0]._source.accountnumber=123\n```\n\n### 2. Add array value properties ending with \"_comma_separated_values\"\n\nTo make it easier to e.g. display array values like tags,\nan additional property is added that combines the array values to a single property,\nthat contains the values in a comma separated way.\nThis newly created property gets the name of the array property followed by \"_comma_separated_values\"\nand is inserted right after the single array values.\n\nFor example these lines...\n\n```javascript\nresponses[0].hits.total.value=1\nresponses[0].hits.hits[0]._source.tags[0]=active\nresponses[0].hits.hits[0]._source.tags[1]=online\n```\n\n...will lead to an additional property that looks like this...\n\n```javascript\nresponses[0].hits.hits[0]._source.tags_comma_separated_values=active, online\n```\n\n### 3. Attach description to matching properties\n\nFor every given description, all properties are searched for matches.\nIf a description matches a property, the description gets attached to it.\nThis can be used to categorize and filter properties.\nThe description builder accepts these ways to configure property matching:\n\n- Equal Mode (default):  \nThe property name needs to match the described pattern exactly. It is not needed to set equal mode.\nThe field name will be (by default) taken from the right most (after the last separator `.`) element of the property name.\nIn the example below the field name will be \"accountnumber\".\nExample:\n\n   ```javascript\n   new datarestructor.PropertyStructureDescriptionBuilder()\n   .propertyPatternEqualMode()\n   .propertyPattern(\"responses.hits.hits._source.accountnumber\")\n   ...\n  ```\n\n- Pattern Mode:  \nThe property name needs to start with the described pattern.\nThe pattern may contain variables inside double curly brackets.  \nThe variable `{{fieldName}}` is a special case which describes from where the field name should be taken.\nIf `{{fieldName}}` is not specified, the field name will be taken from the right most (after the last separator `.`) element of the property name, which is the same behavior as in \"Equal Mode\".\nThis mode needs to set using `propertyPatternTemplateMode`, since the default mode is `propertyPatternEqualMode`.\nExample:  \n\n   ```javascript\n   new datarestructor.PropertyStructureDescriptionBuilder()\n   .propertyPatternTemplateMode()\n   .propertyPattern(\"responses.hits.hits._source.{{fieldName}}\")\n   ...\n  ```\n\n- Index Matching (Optional):  \nIf the source data is structured in an top level array and all property names look pretty much the same\nit may be needed to describe data based on the array index.\nThe index of an property is taken out of its array qualifiers.  \nFor example, the property name `responses[0].hits.hits[1]._source.tags[2]` has the index `0.1.2`.  \nIndex Matching can be combined with property name matching.\nThis example restricts the description to the first top level array:\n\n   ```javascript\n   new datarestructor.PropertyStructureDescriptionBuilder()\n   .indexStartsWith(\"0.\")\n   ...\n  ```\n\n### 4. Removing duplicates (deduplication)\n\nTo remove duplicate properties or to override properties with other ones when they exist,\na `deduplicationPattern` can be defined.\u003cbr/\u003e\u003cbr/\u003e\nVariables (listed below) are put into double curly brackets and will be replaced with the contents of the description and the matching property.  \nIf there are two entries with the same resolved `deduplicationPattern` (=`_identifier.deduplicationId`),\nthe second one will override the first (the first one will be removed).\nExample:\n\n   ```javascript\n   new datarestructor.PropertyStructureDescriptionBuilder()\n   .deduplicationPattern(\"{{category}}--{{type}}--{{index[0]}}--{{index[1]}}--{{fieldName}}\")\n   ...\n  ```\n\n### 5. Grouping\n\nSince data had been flattened in the step 1., it is structured as a list of property names and their values.\nThis non-hierarchical structure is ideal to add further properties, attach descriptions and remove duplicates.\nAfter all, a fully flat structure might not be suitable to display overviews/details or to collect options. \u003cbr/\u003e\u003cbr/\u003e\nThe `groupName` defines the name of the group attribute (defaults to \"group\" if not set). \u003cbr/\u003e\u003cbr/\u003e\nThe `groupPattern` describes, which properties belong to the same group.  \nVariables (listed below) are put into double curly brackets and will be replaced with the contents\nof the description and the matching property.  \nThe `groupPattern` will be resolved to the `_identifier.groupId`. Every property, that leads to a\nnew groupId gets a new attribute named by the `groupName`, where this entry and all others of the\nsame group will be put into. Example:  \n\n   ```javascript\n   new datarestructor.PropertyStructureDescriptionBuilder()\n   .groupName(\"details\")\n   .groupPattern(\"{{category}}--{{type}}--{{index[0]}}--{{index[1]}}\")\n   ...\n  ```\n\n### 6. Moving groups (destination group)\n\nAfter grouping in step 5., every property containing a group and the remaining non-grouped properties\nare listed one after another. To organize them further, a group can be moved beneath another (destination) group. \u003cbr/\u003e\u003cbr/\u003e\nThe `groupDestinationPattern` contains the pattern of the group to where the own group should be moved.\nVariables (listed below) are put into double curly brackets and will be replaced with the contents\nof the description and the matching property.  \nOptionally, the `groupDestinationName` can be specified to rename the group when it is moved. Default is the value of `groupName`.\nExample, where the details group is moved to the summary, because the group destination pattern\nof the details resolves to the same id as the resolved group pattern of the summary:\n\n   ```javascript\n  var summaryDescription = new datarestructor.PropertyStructureDescriptionBuilder()\n    .category(\"account\")\n    .type(\"summary\")\n    .groupName(\"summaries\")\n    .groupPattern(\"{{category}}--{{type}}--{{index[0]}}--{{index[1]}}\")\n    ...\n\n  var detailsDescription = new datarestructor.PropertyStructureDescriptionBuilder()\n   .groupDestinationPattern(\"account--summary--{{index[0]}}--{{index[1]}}\")\n   .groupDestinationName(\"details\")\n   ...\n  ```\n\n### 7. Convert data into an array of DescribedFields\n\nThe result is finally converted into an array of [DescribedDataField](#describeddatafield)s.\n\n## Types, fields, variables\n\nThis section lists the types and their fields in detail (mostly taken from jsdoc).\nEvery field can be used as variable in double curly brackets inside pattern properties.\nAdditionally, single elements of the index can be used by specifying the index position e.g. `{{index[0]}}` (first), `{{index[1]}}` (second),...\n\n### PropertyStructureDescription (input description)\n\n- **type** - \"\"(default). Some examples: \"summary\" for e.g. a list overview. \"detail\" e.g. when a summary is selected. \"filter\" e.g. for field/value pair results that can be selected as search parameters.\n- **category** - name of the category. Default = \"\". Could contain a symbol character or a short domain name. (e.g. \"city\")\n- **abbreviation** - \"\"(default). One optional character, a symbol character or a short abbreviation of the category.\n- **image** - \"\"(default). One optional path to an image resource.\n- **propertyPatternTemplateMode** - boolean \"false\"(default): property name needs to be equal to the pattern. \"true\" allows variables like `{{fieldname}}` inside the pattern.\n- **propertyPattern** - property name pattern (without array indices) to match. A pattern may contain variables in double curly brackets {{variable}}. See also: [variables](#describeddatafield-public-fields), [further details](#describeddatafield-public-functions)\n- **indexStartsWith** - \"\"(default) matches all ids. String that needs to match the beginning of the id. E.g. \"1.\" will match id=\"1.3.4\" but not \"0.1.2\".\n- **groupName** - name of the property, that contains grouped entries. Default=\"group\".\n- **groupPattern** - Pattern that describes how to group entries. \"groupName\" defines the name of this group. A pattern may contain variables in double curly brackets {{variable}}. See also: [variables](#describeddatafield-public-fields), [further details](#describeddatafield-public-functions)\n- **groupDestinationPattern** - Pattern that describes where the group should be moved to. Default=\"\"=Group will not be moved. A pattern may contain variables in double curly brackets {{variable}}. See also: [variables](#describeddatafield-public-fields), [further details](#describeddatafield-public-functions)\n- **groupDestinationName** - (default=groupName) Name of the group when it had been moved to the destination.\n- **deduplicationPattern** - Pattern to use to remove duplicate entries. A pattern may contain variables in double curly brackets {{variable}}. See also: [variables](#describeddatafield-public-fields), [further details](#describeddatafield-public-functions)\n\n### DescribedDataField\n\nThis is the data structure of a single output element representing a field.\nBeside the properties described below, the described data field can also contain\ncustom properties containing groups (arrays) of sub fields of type DescribedDataField.\n\nBefore version 3.0.0 this structure was named [DescribedEntry](#describedentry) and also contained internal fields.  \nSince 3.0.0 and above, [DescribedEntry](#describedentry) is only used internally and is not public any more.\n\n#### DescribedDataField Public Fields\n\n- **category** - category of the result from the PropertyStructureDescription using a short name or e.g. a symbol character\n- **type** - type of the result from PropertyStructureDescription\n- **abbreviation** - one optional character, a symbol character or a short abbreviation of the category\n- **image** - one optional path to an image resource\n- **index** - contains an array of numbers representing the hierarchical index for list entries (and their sub lists ...). Example: `\"responses[2].hits.hits[4]._source.name\"` will have an index of [2,4].\n- **groupNames** - contains an array of String names. Every name represents a group that had been dynamically added as property. Groups should be added using [DescribedDataFieldGroup](#describeddatafieldgroup), which will also update the group names.\n- **displayName** - display name extracted from the point separated hierarchical property name, e.g. \"Name\"\n- **fieldName** - field name extracted from the point separated hierarchical property name, e.g. \"name\"\n- **value** - content of the field\n\n#### DescribedDataField Public Functions\n\nSince version 3.0.0 and above, there are no functions any more.\n\n#### Described groups\n\n- **\"name of described group\"** as described in PropertyStructureDescription\n- **\"names of moved groups\"** as described in PropertyStructureDescription of the group that had been moved\n\n### DescribedDataFieldGroup\n\nThis helper was added with version 3.0.0. It adds groups to [DescribedDataField](#describeddatafield)s.\nThese groups are dynamically added properties that contain an array of sub fields also of type [DescribedDataField](#describeddatafield).\n\n#### DescribedDataFieldGroup Public Functions\n\n- **addGroupEntry(groupName, entry)** Adds an entry to the given group. If the group does not exist, it will be created and added to the \"groupNames\".\n- **addGroupEntries(groupName, entries)** Adds an array of entries to the given group. If the group does not exist, it will be created and added to the \"groupNames\".\n\n### DescribedEntry\n\nSince 3.0.0 and above, DescribedEntry is only used internally and is not public any more.\nIt is documented here for sake of completeness and for maintenance purposes.\nSee JSDoc for a more comprehensive reference.\n\n#### Properties\n\n- **describedField** - contains the [DescribedDataField](#describeddatafield)\n- **isMatchingIndex** - true, if _identifier.index matches the described \"indexStartsWith\"\n- **_identifier** - internal structure for identifier. Avoid using it outside since it may change.\n- **_identifier.index** - array indices in hierarchical order separated by points, e.g. \"0.0\"\n- **_identifier.value** - the (single) value of the \"flattened\" property, e.g. \"Smith\"\n- **_identifier.propertyNamesWithArrayIndices** - the \"original\" flattened property name in hierarchical order separated by points, e.g. \"responses[0].hits.hits[0]._source.name\"\n- **_identifier.propertyNameWithoutArrayIndices** - same as propertyNamesWithArrayIndices but without array indices, e.g. \"responses.hits.hits._source.name\"\n- **_identifier.groupId** - Contains the resolved groupPattern from the PropertyStructureDescription. Entries with the same id will be grouped into the \"groupName\" of the PropertyStructureDescription.\n- **_identifier.groupDestinationId** - Contains the resolved groupDestinationPattern from the PropertyStructureDescription. Entries with this id will be moved to the given destination group.\n- **_identifier.deduplicationId** - Contains the resolved deduplicationPattern from the PropertyStructureDescription. Entries with the same id will be considered to be a duplicate and hence removed.\n- **_description** - PropertyStructureDescription for internal use. Avoid using it outside since it may change.\n\n### Template Resolver\n\nAn simple template resolver is included and provided as separate module.\nHere is an example on how to use it:\n\n```javaScript\nvar template_resolver = require(\"templateResolver\");\nvar sourceDataObject = {type: \"MyType\", category: \"MyCategory\"};\nvar resolver = new template_resolver.Resolver(sourceDataObject);\nvar template = \"{{type}}-{{category}}\";\nvar resolvedString = resolver.resolveTemplate(template);\n//resolvedString will contain \"MyType-MyCategory\"\n```\n\n#### Template Resolver Public Functions\n\n- **resolveTemplate** - resolves the given template string. The template may contain variables in double curly brackets:\n  - All [public fields](#describeddatafield-public-fields) can be used as variables, e.g. `\"{{fieldName}}\"`, `\"{{displayName}}\"`, `\"{{value}}\"`.\n  - Described groups that contain an array of [described entries](#describeddatafield) can also be used, e.g. `\"{{summaries[0].value}}\"`.\n  - Parts of the index can be inserted by using e.g. `\"{{index[1]}}\"`.\n  - Besides the meta data, a described field can be used directly by its \"fieldName\", e.g. `\"{{customernumber}}\"` will be replaced by `123`, if the structure contains `fieldname=\"customernumber\", value=\"123\"`. This also applies to sub groups, e.g. `\"{{details.customernumber}}\"` will be replaced by `321`, if the structure contains `details[4].fieldname=\"customernumber\", details[4].value=\"321\"`.\n\n### TransformConfig\n\nAn comprehensive and up to date reference can be found here: [TransformConfig JSDoc](https://joht.github.io/data-restructor-js/module-datarestructor.html#.TransformConfig).\n\nThe restructured data is by nature hierarchical and may contain cyclic data references. Fields may contain groups of fields that may contain groups of fields....\nSince JSON can't be generated out of objects with cyclic references, sub-structures are expressed by copies.\nThat leads to recursion and duplication, that need to be limited. This can be configured here.\n\n#### TransformConfig Properties\n\n- **debugMode** boolean value, that enables/disables detailed logging\n- **maxRecursionDepth** numeric value that defines the maximum recursion depth\n- **removeDuplicationAboveRecursionDepth** numeric value that defines the recursion depth, above which duplications inside groups will be removed.\n\n#### Public functions (provides by \"Transform\")\n\n- **enableDebugMode(boolean)** boolean value, that enables/disables detailed logging\n- **setMaxRecursionDepth(number)** numeric value that defines the maximum recursion depth\n- **setRemoveDuplicationAboveRecursionDepth(number)** numeric value that defines the recursion depth, above which duplications inside groups will be removed.\n\n## Related blog articles\n\n- [Most effective ways to push within GitHub Actions](https://joht.github.io/johtizen/build/2022/01/20/github-actions-push-into-repository.html)\n- [Continuous Integration for JavaScript with npm](https://joht.github.io/johtizen/build/2021/02/21/continuous-integration-javascript.html)\n\n## References\n\n- [Mozilla MDN web docs - polyfill for 'Array.filter'](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter#Polyfill) for browser compatibility\n- [Mozilla MDN web docs - polyfill for 'Array.forEach'](https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach#Polyfill) for browser compatibility (references [es5.github.io](http://es5.github.io/#x15.4.4.18))\n- [Mozilla MDN web docs - polyfill for 'Array.indexOf'](https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf#Polyfill) for browser compatibility\n- [Mozilla MDN web docs - polyfill for 'Array.isArray'](https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray#Compatibility) for browser compatibility\n- [Mozilla MDN web docs - polyfill for 'String.startsWith'](https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith#Polyfill) for browser compatibility\n- [Token Posts - polyfill for 'Object.keys'](http://tokenposts.blogspot.com/2012/04/javascript-objectkeys-browser.html) for browser compatibility\n\n## Credits\n\nAlthough this project doesn't use any runtime dependencies, it is created using these great tools:\n\n- [ESLint](https://eslint.org) - [MIT License](https://github.com/eslint/eslint/blob/master/LICENSE)\n- [istanbul-badges-readme](https://www.npmjs.com/package/istanbul-badges-readme) - [MIT License](https://github.com/olavoparno/istanbul-badges-readme/blob/develop/LICENSE)\n- [Jasmine](https://jasmine.github.io) - [MIT License](https://github.com/jasmine/jasmine/blob/main/MIT.LICENSE)\n- [JSDoc](https://jsdoc.app) - [Apache Licence 2.0](https://github.com/jsdoc/jsdoc/blob/master/LICENSE)\n- [merger-js](https://github.com/joao-neves95/merger-js) - [GNU General Public License v3.0](https://github.com/joao-neves95/merger-js/blob/master/LICENSE.md)\n- [NYC aka Istanbul](https://istanbul.js.org) - [ISC License](https://github.com/istanbuljs/nyc/blob/master/LICENSE.txt)\n- [PARCEL](https://v2.parceljs.org) - [MIT License](https://github.com/parcel-bundler/parcel/blob/v2/LICENSE)\n- [merger-js](https://github.com/joao-neves95/merger-js) - [GNU General Public License v3.0](https://github.com/joao-neves95/merger-js/blob/master/LICENSE.md)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoht%2Fdata-restructor-js","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjoht%2Fdata-restructor-js","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoht%2Fdata-restructor-js/lists"}