0

I'm trying to use a JSON file in Angular, but the reference file isn't true JSON. What's the best way to access it, and parse it, into true JSON, to be used?

I'm trying to access notTrue.json in a controller in angular.js, like in the file structure below. And parse notTrue.json into a real JSON format.

Example file structure:

index.html
js (folder)
 - angular.js
 - notTrue.json
 - etc
css (folder)
img (folder)

Example non-JSON format, notTrue.json file:

var Foo = [{
    'bar': 'Hello World',
    'subItem': {
        'phone1': '(555) 543-213',
        'email': '[email protected]'
    }
}, {
    'bar': 'Goodnight Moon',
    'subItem': {
        'phone1': '(555) 521-3344',
        'email': '[email protected]'
    }
}];

I want to get it into a proper JSON format, like below:

[{
    "bar": "Hello World",
    "subitem": {
        "phone1": "(555) 543-213",
        "email": "[email protected]"
    }
}, {
    "bar": "Goodnight Moon",
    "subitem": {
        "phone1": "(555) 521-3344",
        "email": "[email protected]"
    }
}]
5
  • The first is not JSON format, it is an object. JSON is a string. Are you sure you didn't want to say that Foo is a string? Can you clarify? Commented Dec 4, 2015 at 23:47
  • As evil as it is, eval might do what you need. Seems like you're saying you have some arbitrary Javascript text you need to interpret, which is what eval does. That being said, you don't even have JSON like data, with the var Foo =, you just have javascript. If that part is well known, you can eval and then access foo to retrieve the object. Otherwise, the real answer is to clean up your data sources. It should be sanitized before it hits the client. Commented Dec 4, 2015 at 23:47
  • @trincot - yes, the first is an object. The 'JSON' file its from is not correctly formatted to begin with. (Not real JSON). Commented Dec 5, 2015 at 0:07
  • So you did convert the not-JSON file to an object called Foo. I am lost as to what is your question then, because converting Foo to valid JSON is trivial. Commented Dec 5, 2015 at 0:09
  • @trincot - the external file is the Foo object. It's not in local files. I'm trying to grab it, then parse it into valid JSON. That's where I'm stuck. Commented Dec 5, 2015 at 2:47

2 Answers 2

1

If this notTrue.json file is static, in the sense that it is already there when the user accesses index.html and will not change during the user's use of the application, then it is best to include notTrue.json via a script tag, before loading angular.js, like this:

<script src="js/notTrue.json"></script>
<script src="js/angularjs"></script>

Then you will have access to the Foo object in your application. The following code illustrates this by outputting the JSON format on screen:

<div ng-app="myApp" ng-controller="myControler">
   <pre>{{json}}</pre>
</div>

<script>
    var app = angular.module('myApp', []);
    app.controller('myControler', function($scope, $window) {
        // window.Foo was defined when loading notTrue.js 
        // Convert it to JSON string (pretty printed)
        $scope.json = JSON.stringify($window.Foo, null, 4);
    });
</script>

In the above example, the on-page output will be:

[
    {
        "bar": "Hello World",
        "subItem": {
            "phone1": "(555) 543-213",
            "email": "[email protected]"
        }
    },
    {
        "bar": "Goodnight Moon",
        "subItem": {
            "phone1": "(555) 521-3344",
            "email": "[email protected]"
        }
    }
]

Note that the pre tag and the extra arguments to the JSON.stringify method are used to get the JSON string pretty printed. But this is not essential to your question.

Dynamically loading notTrue.js

If on the other hand, you want to defer loading notTrue.js until some event takes place, because its contents might change between page load and that event, then you could use $http.get.

In the following example, the file is loaded upon a button click, and the JSON format is output on screen:

<div ng-app="myApp" ng-controller="myControler">
   <button ng-click="load('js/notTrue.json')">Load</button>
   <pre>{{json}}</pre>
</div>

<script>
    var app = angular.module('myApp', []);
    app.controller('myControler', function($scope, $http) {
        // Define what should happen on button click:
        $scope.load = function(file) {
            $http.get(file).then(function(response) {
                // Extract from the retrieved file contents
                // the part between the first "=" and 
                // final (optional) semi-colon
                var txt = response.data.replace(/^.*?=([\S\s]*?);?\s*$/, '$1');
                // Evaluate that text, adding brackets to avoid misinterpretation
                // when text starts with opening brace.
                var Foo = eval('(' + txt + ')');
                // and convert to JSON string (pretty printed)
                $scope.json = JSON.stringify(Foo, null, 4);
            });
        };
    });
</script> 

The output is the same as with the first solution.

Note that with this method, the loaded file must reside on the same server, which I understand is your case.

Only go for this solution if the first one does not suit your needs.

You will want to add checks and deal with potential errors for when the file is not found, does not have the expected format, etc.

Finally, be careful with using eval: only use it when you trust the source, which I believe is the case here.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks @trincot, this is exactly what I was looking for!
0

The first example is plain javascript code - and you say you trust the source.

If this code has been returned in response to a server request, and can access it as responseText, say, then

var JSONtext = JSON.stringify( eval(responseText.replace(/[^=]*=/,"")));

should do the job. (The regular expression replacement takes out the variable definition).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.