{ "id": "171855", "key": "TIMOB-26165", "fields": { "issuetype": { "id": "1", "description": "A problem which impairs or prevents the functions of the product.", "name": "Bug", "subtask": false }, "project": { "id": "10153", "key": "TIMOB", "name": "Titanium SDK/CLI", "projectCategory": { "id": "10100", "description": "Titanium and related SDKs used in application development", "name": "Client" } }, "fixVersions": [ { "id": "20238", "description": "", "name": "Release 7.5.0", "archived": false, "released": true, "releaseDate": "2018-11-15" } ], "resolution": { "id": "1", "description": "A fix for this issue is checked into the tree and tested.", "name": "Fixed" }, "resolutiondate": "2018-08-24T17:23:21.000+0000", "created": "2018-06-28T11:27:25.000+0000", "priority": { "name": "High", "id": "2" }, "labels": [ "ios", "json", "parity" ], "versions": [ { "id": "20102", "name": "Release 7.1.1", "archived": false, "released": true, "releaseDate": "2018-05-02" }, { "id": "20099", "name": "Release 7.2.0", "archived": false, "released": true, "releaseDate": "2018-06-14" } ], "issuelinks": [], "assignee": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "updated": "2018-08-24T17:23:53.000+0000", "status": { "description": "The issue is considered finished, the resolution is correct. Issues which are closed can be reopened.", "name": "Closed", "id": "6", "statusCategory": { "id": 3, "key": "done", "colorName": "green", "name": "Done" } }, "components": [ { "id": "10206", "name": "iOS", "description": "iOS Platform" } ], "description": "h5.Description\r\n\r\nWhen requiring a JSON file where a value contains a single quote an error like below is thrown, this works fine on Windows/Android\r\n\r\n{code}\r\n[ERROR] Script Error {\r\n[ERROR] column = 32;\r\n[ERROR] line = 2;\r\n[ERROR] message = \"Unexpected identifier 's'. Expected ')' to end an argument list.\";\r\n[ERROR] sourceURL = \"file:///Users/eharris/Library/Developer/CoreSimulator/Devices/EE6CA02F-4F3A-4407-9929-FEAC97512C66/data/Containers/Bundle/Application/4B53071A-F963-4006-9FEC-DA1C01E87548/ticreateapp.app/jsonfile.json\";\r\n[ERROR] stack = \" at require@[native code]\\n at global code(/app.js:1:32)\";\r\n[ERROR] }\r\n[ERROR] Script Error Module \"jsonfile.json\" failed to leave a valid exports object\r\n{code}\r\n\r\n*Workaround*\r\nRead the file in like {{JSON.parse(Ti.Filesystem.getFile('file.json').read())}}\r\n\r\n\r\nh5.Steps to reproduce\r\n\r\n# Add the below into a JSON file under your project\r\n{code}\r\n{\r\n\t\"foo\": \"Singlequotes can ruin one's day\"\r\n}\r\n{code}\r\n# Add a require statement into your code that requires the file\r\n\r\nh5.Actual\r\n\r\nError like the above is thrown\r\n\r\nh5.Expected\r\n\r\nFile should be imported", "attachment": [ { "id": "65308", "filename": "amber.json", "author": { "name": "eharris", "key": "eharris", "displayName": "Ewan Harris", "active": true, "timeZone": "Europe/Dublin" }, "created": "2018-06-28T18:48:19.000+0000", "size": 8109, "mimeType": "application/json" } ], "flagged": false, "summary": "iOS: Requiring a JSON file that contains single quotes throws error", "creator": { "name": "eharris", "key": "eharris", "displayName": "Ewan Harris", "active": true, "timeZone": "Europe/Dublin" }, "subtasks": [], "reporter": { "name": "eharris", "key": "eharris", "displayName": "Ewan Harris", "active": true, "timeZone": "Europe/Dublin" }, "environment": null, "closedSprints": [ { "id": 1053, "state": "closed", "name": "2018 Sprint 15 SDK", "startDate": "2018-07-15T21:52:05.453Z", "endDate": "2018-07-29T21:52:00.000Z", "completeDate": "2018-07-29T22:25:11.723Z", "originBoardId": 114 } ], "comment": { "comments": [ { "id": "438826", "author": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "body": "Could you check if that also happened before SDK 6.2.0? It may be caused by https://github.com/appcelerator/titanium_mobile/pull/9106 then.", "updateAuthor": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "created": "2018-06-28T16:52:17.000+0000", "updated": "2018-06-28T16:52:17.000+0000" }, { "id": "438827", "author": { "name": "eharris", "key": "eharris", "displayName": "Ewan Harris", "active": true, "timeZone": "Europe/Dublin" }, "body": "[~hknoechel] It still occurs on 6.1.1.GA, I think the [logic for require-ing a JSON file|https://github.com/appcelerator/titanium_mobile/blob/eeffeedd4bc7f20ad5211b69461c0e9b128c0d7b/iphone/Classes/KrollBridge.m#L890-L907] doesn't pass through there from what I can see. Maybe it should?", "updateAuthor": { "name": "eharris", "key": "eharris", "displayName": "Ewan Harris", "active": true, "timeZone": "Europe/Dublin" }, "created": "2018-06-28T17:18:13.000+0000", "updated": "2018-06-28T17:18:13.000+0000" }, { "id": "438833", "author": { "name": "eharris", "key": "eharris", "displayName": "Ewan Harris", "active": true, "timeZone": "Europe/Dublin" }, "body": "Changing [this line|https://github.com/appcelerator/titanium_mobile/blob/eeffeedd4bc7f20ad5211b69461c0e9b128c0d7b/iphone/Classes/KrollBridge.m#L899] to \r\n{noformat}\r\ndata = [data stringByReplacingOccurrencesOfString:@\"'\" withString:@\"\\\\'\"];\r\n{noformat}\r\nfixes for the original issue, but still errors out on the attached amber.json with the below\r\n\r\n{code}\r\n[ERROR] Script Error {\r\n[ERROR] column = 143;\r\n[ERROR] line = 1;\r\n[ERROR] message = \"JSON Parse error: Unterminated string\";\r\n[ERROR] sourceURL = \"file:///Users/eharris/Library/Developer/CoreSimulator/Devices/EE6CA02F-4F3A-4407-9929-FEAC97512C66/data/Containers/Bundle/Application/E4B9915B-D15D-420F-95F1-935C3F4CC4EB/Amber.app/amber.json\";\r\n[ERROR] stack = \" at parse@[native code]\\n at (/amber.json:1:143)\\n at global code(/amber.json:75:70)\\n at require@[native code]\\n at global code(/app.js:1:20)\";\r\n[ERROR] }\r\n[ERROR] Script Error Module \"amber.json\" failed to leave a valid exports object\r\n{code}", "updateAuthor": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "created": "2018-06-28T18:48:09.000+0000", "updated": "2018-07-26T15:09:53.000+0000" }, { "id": "438835", "author": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "body": "There built-in serializer classes in iOS these days (I think iOS7+). I will try to refactor the JSON-import logic using {{NSJSONSerialization}}, which has options to handle how the JSON should be serialized and which parts of it should be retained how.\r\n\r\n*EDIT*: This here works fine:\r\n{code:js}\r\nvar win = Ti.UI.createWindow({\r\n backgroundColor: '#fff'\r\n});\r\n\r\nvar btn = Ti.UI.createButton({\r\n title: 'Trigger'\r\n});\r\n\r\nbtn.addEventListener('click', function() {\r\n try {\r\n var payload = JSON.parse(Ti.Filesystem.getFile('amber.json').read());\r\n alert('SDK: ' + payload.sdk);\r\n } catch (e) {\r\n Ti.API.error('Error parsing JSON: \\n' + e);\r\n }\r\n});\r\n\r\nwin.add(btn);\r\nwin.open();\r\n{code}", "updateAuthor": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "created": "2018-06-28T20:29:49.000+0000", "updated": "2018-06-28T20:34:11.000+0000" }, { "id": "440539", "author": { "name": "eharris", "key": "eharris", "displayName": "Ewan Harris", "active": true, "timeZone": "Europe/Dublin" }, "body": "[~hknoechel] Reading the file and JSON.parse'ing it works fine, but it doesn't work from require. The file is valid as it works on Titanium Windows/Android and Node. What extra info is needed?", "updateAuthor": { "name": "eharris", "key": "eharris", "displayName": "Ewan Harris", "active": true, "timeZone": "Europe/Dublin" }, "created": "2018-08-07T08:53:41.000+0000", "updated": "2018-08-07T08:53:41.000+0000" }, { "id": "440541", "author": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "body": "Reopening since it is reproducible with the following test-case:\r\n{code:js}\r\nvar amber = require('amber'); // expects a \"amber.json\" to be in the resources\r\n\r\nvar win = Ti.UI.createWindow({\r\n backgroundColor: '#fff'\r\n});\r\n\r\nwin.open();\r\n{code}", "updateAuthor": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "created": "2018-08-07T10:02:45.000+0000", "updated": "2018-08-07T10:03:05.000+0000" }, { "id": "440543", "author": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "body": "Fixed it. We can use native JSON-parse/stringify methods for this nowadays.\r\n\r\nPR: https://github.com/appcelerator/titanium_mobile/pull/10238\r\n\r\nTest-Case:\r\n{code:js}\r\nvar amber = require('amber'); // Looks for \"amber.json\" in Resources/ (classic) or app/assets (Alloy)\r\n\r\nvar win = Ti.UI.createWindow({\r\n backgroundColor: '#fff'\r\n});\r\n\r\nvar btn = Ti.UI.createButton({\r\n title: 'Trigger'\r\n});\r\n\r\nbtn.addEventListener('click', function() {\r\n Ti.API.info(amber.sdk);\r\n});\r\n\r\nwin.add(btn);\r\nwin.open();\r\n{code}\r\n\r\nExpected result: A console log with \"7.4.0.v20180627024922\".", "updateAuthor": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "created": "2018-08-07T10:17:48.000+0000", "updated": "2018-08-07T10:30:23.000+0000" }, { "id": "440791", "author": { "name": "smohammed", "key": "smohammed", "displayName": "Samir Mohammed", "active": true, "timeZone": "America/Los_Angeles" }, "updateAuthor": { "name": "smohammed", "key": "smohammed", "displayName": "Samir Mohammed", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2018-08-15T09:44:11.000+0000", "updated": "2018-08-15T09:44:11.000+0000" } ], "maxResults": 9, "total": 9, "startAt": 0 } } }