What is the $$hashKey added to my JSON.stringify result

JavascriptJqueryJsonAngularjs

Javascript Problem Overview


I have tried looking on the Mozilla JSON stringify page of their docs as well as here on SO and Google but found no explanation. I have used JSON.stringify many time but never come across this result.

I have an array of JSON objects:

[    {        "param_2": "Description 1",        "param_0": "Name 1",        "param_1": "VERSION 1"    },    {        "param_2": "Description 2",        "param_0": "Name 2",        "param_1": "VERSION 2"    },    {        "param_2": "Description 3",        "param_0": "Name 3",        "param_1": "VERSION 3"    }]

It is attached to my $scope. In order to POST them as one parameter, I used the JSON.stringify() method and receive the following:

   [
        {
            "param_2": "Description 1",
            "param_0": "Name 1",
            "param_1": "VERSION 1",
            "$$hashKey": "005"
        },
        {
            "param_2": "Description 2",
            "param_0": "Name 2",
            "param_1": "VERSION 2",
            "$$hashKey": "006"
        },
        {
            "param_2": "Description 3",
            "param_0": "Name 3",
            "param_1": "VERSION 3",
            "$$hashKey": "007"
        }
    ]

I am just curious about what the $$hashkey property is exactly, as I expected something more similar to the following from the stringify method (that is, without the $$hashkey):

[    {        "1":{            "param_2": "Description 1",            "param_0": "Name 1",            "param_1": "VERSION 1"        },         "2":{            "param_2": "Description 2",            "param_0": "Name 2",            "param_1": "VERSION 2"        },         "3":{            "param_2": "Description 3",            "param_0": "Name 3",            "param_1": "VERSION 3"        }    }]

I am not sure if it is a factor, but I am using the following:

  • Angularjs 1.1.5,
  • JQuery 1.8.2
  • Spring 3.0.4

I'm also using Spring security 3.0.7 on the Server side.

It is not causing me any issues, but I would like to know the cause and reason for the $$hashkey

Javascript Solutions


Solution 1 - Javascript

Angular adds this to keep track of your changes, so it knows when it needs to update the DOM.

If you use angular.toJson(obj) instead of JSON.stringify(obj) then Angular will strip out these internal-use values for you.

Also, if you change your repeat expression to use the track by {uniqueProperty} suffix, Angular won't have to add $$hashKey at all. For example

<ul>
    <li ng-repeat="link in navLinks track by link.href">
        <a ng-href="link.href">{{link.title}}</a>
    </li>
</ul>

Just always remember you need the "link." part of the expression - I always tend to forget that. Just track by href will surely not work.

Solution 2 - Javascript

In my use case (feeding the resulting object to X2JS) the recommended approach

data = angular.toJson(source);

help to remove the $$hashKey properties, but the result could then no longer be processed by X2JS.

data = angular.copy(source);

removed the $$hashKey properties as well, but the result remained usable as a parameter for X2JS.

Solution 3 - Javascript

It comes with the ng-repeat directive usually. To do dom manipulation AngularJS flags objects with special id.

This is common with Angular. For example if u get object with ngResource your object will embed all the resource API and you'll see methods like $save, etc. With cookies too AngularJS will add a property __ngDebug.

Solution 4 - Javascript

If you don't want to add id's to your data, you could track by the index in the array, which will cause the items to be keyed by their position in the array instead of their value.

Like this:

var myArray = [1,1,1,1,1];

<li ng-repeat="item in myArray track by $index">

Solution 5 - Javascript

If you are using Angular 1.3 or above, I recommend that you use "track by" in your ng-repeat. Angular doesn't add a "$$hashKey" property to the objects in your array if you use "track by". You also get performance benefits, if something in your array changes, angular doesn't recreate the entire DOM structure for your ng-repeat, it instead recreates the part of the DOM for the values in your array that have changed.

Solution 6 - Javascript

Update : From Angular v1.5, track by $index is now the standard syntax instead of using link as it gave me a ng-repeat dupes error.

I ran into this for a nested ng-repeat and the below worked.

<tbody>
    <tr ng-repeat="row in data track by $index">
    <td ng-repeat="field in headers track by $index">{{row[field.caption] }}</td>
</tr>

Solution 7 - Javascript

Here is how you can easily remove the $$hashKey from the object:

$scope.myNewObject = JSON.parse(angular.toJson($scope.myObject))

$scope.myObject - Refers to the Object that you want to perform the operation upon i.e. remove the $$hashKey from

$scope.myNewObject - Assign the modified original object to the new object so it can be used as necessary

Solution 8 - Javascript

https://www.timcosta.io/angular-js-object-comparisons/

Angular is pretty magical the first time people see it. Automatic DOM updates when you update a variable in your JS, and the same variable will update in your JS file when someone updates its value in the DOM. This same functionality works across page elements, and across controllers.

The key to all of this is the $$hashKey Angular attaches to objects and arrays used in ng-repeats.

This $$hashKey causes a lot of confusion for people who are sending full objects to an API that doesn't strip extra data. The API will return a 400 for all of your requests, but that $$hashKey just wont go away from your objects.

Angular uses the $$hashKey to keep track of which elements in the DOM belong to which item in an array that is being looped through in an ng-repeat. Without the $$hashKey Angular would have no way to apply changes the occur in the JavaScript or DOM to their counterpart, which is one of the main uses for Angular.

Consider this array:

users = [  
    {
         first_name: "Tim"
         last_name: "Costa"
         email: "[email protected]"
    }
]

If we rendered that into a list using ng-repeat="user in users", each object in it would receive a $$hashKey for tracking purposes from Angular. Here are two ways to avoid this $$hashKey.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionjonnieView Question on Stackoverflow
Solution 1 - JavascriptDavid BoikeView Answer on Stackoverflow
Solution 2 - Javascriptrob2universeView Answer on Stackoverflow
Solution 3 - JavascriptThomas PonsView Answer on Stackoverflow
Solution 4 - JavascriptMichael Falck WedelgårdView Answer on Stackoverflow
Solution 5 - JavascriptAjay UllalView Answer on Stackoverflow
Solution 6 - JavascriptVinayView Answer on Stackoverflow
Solution 7 - JavascriptDevnerView Answer on Stackoverflow
Solution 8 - Javascriptalfishan aqeelView Answer on Stackoverflow