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

169,212

Solution 1

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

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

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

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

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.

Share:
169,212

Related videos on Youtube

jonnie
Author by

jonnie

Updated on December 23, 2020

Comments

  • jonnie
    jonnie over 3 years

    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

  • Nilesh
    Nilesh almost 10 years
    how should i remove these properties? Does angular provide any way to do that?
  • Josue Alexander Ibarra
    Josue Alexander Ibarra almost 10 years
    Angular models will break if you try to remove that property, I recommend to copy the variable. See @David-Boike 's answer on how to filter out the hashkey
  • artuska
    artuska over 8 years
    Are there any performance tests about «track by» vs «$$hashKey»? (UPD. Ok, I've googled it and «track by» is more preferrable)
  • Christophe Roussy
    Christophe Roussy over 8 years
    @artuska tracking by id is very straightforward as no hashes have to be computed you just reuse existing ids or increment a counter...
  • Lewen
    Lewen about 8 years
    and if you have a filter to apply, here is the correct order: item in somelist | filter:somefilter track by item.key, don't write the filter at the end of the line !
  • vipin Paliwal
    vipin Paliwal over 7 years
    Note! I was using an array with a clone method which copied then inserted elements into an array, which was then rendered by an ng-repeat. I was getting angular 'duplicate key' errors when using JSON.parse(JSON.stringify(obj)) to clone my element. Using JSON.parse(angular.toJson(obj)); fixed things. Thanks!
  • phil
    phil about 7 years
    You can also use the One Time Binding feature using double colon :: to prevent it from updating if you are only displaying data. <a ng-href="link.href">{{::link.title}}</a>
  • Martin Hlavňa
    Martin Hlavňa almost 7 years
    Just to clarify - attribute used in track by expression have to be unique across repeated collection. $index is one option. In most cases it is sufficient, but sometimes you might find useful to track by unique attribute.(id,...)
  • sevcsik
    sevcsik over 6 years
    I find this unnecessarily complex. You could just remove that single field - or every field starting with $. But probably you don't need to -- see the other answers.
  • Gitesh Purbia
    Gitesh Purbia over 6 years
    Also, if you change your repeat expression to use the track by {uniqueProperty} suffix, Angular won't have to add $$hashKey at all. this line resolve many problems for me :) :) thanks
  • Md Aslam
    Md Aslam over 5 years
    @David, Hi David, I have one clarification that Is there any possibility to $$haskey goes duplication? I have used JSOn.stringify(Obj) and I am able to see duplicate key in DB.
  • neatcoding
    neatcoding about 4 years
    That requires assumption that order of your items will never change. :)
  • neatcoding
    neatcoding about 4 years
    That requires assumption that order of your items will never change. :)