简体   繁体   中英

How to dynamically change JSON key (including its children keys) in Javascript?

I am fetching a JSON from an endpoint and I would like to insert it into my mongoDB database. The problem is that some keys that comes from the JSON have a "." inside it and mongoDB throws an error when it suppose to insert this kind of key, for example:

object: {
"DR.No": 1
}

This is the actual endpoint I am fetching: https://api.opensea.io/api/v1/asset_contracts/ It is an array of objects, some of them have a "traits" object which sometimes has these kind of key-value (Ctrl+F and search for "DR." to see what I mean).

When I deleted this section everything worked well.

app.post("/something", (req, res, next) => {
   fetch("https://api.opensea.io/api/v1/asset_contracts/")
  .then(r => r.json())
  .then(data => {
    for (let i = 0; i < data.length; i++) {
      delete  data[i].traits; //works when deleted, I need it though
      ...

I need the traits section. I would like to replace all of the dots with commas. Therefore I need to change the key's and its children keys name dynamically.

Similar questions focus more on how to include the . part in mongoDB than to dynamically change the key (this is the solution I desire)

One possible way to do it is to re write the keys into a new object like this:

let obj = {};
let o = { "DR.No":1, "foo": 2 };
let keys = Object.keys(o);
for(let i = 0;i < keys.length;i++) {  
    let key = keys[i];
    obj[key.replace(".",",")] = o[key] 
}
JSON.stringify(obj,null,2)

"{
  "DR,No": 1,
  "foo": 2
}"

Or if there are many dots:

let obj = {};
let o = { "DR.No.Blah.Dots.ToMany":1, "Weird.Dots.In.Keys": 2 };
let keys = Object.keys(o);
for(let i = 0;i < keys.length;i++) {  
    let key = keys[i];
    let originalKey = key;
    key = key.split(".").join(",");
    obj[key] = o[originalKey] 
}
JSON.stringify(obj,null,2)
"{
  "DR,No,Blah,Dots,ToMany": 1,
  "Weird,Dots,In,Keys": 2
}"

If you want the keys to not have punctuation in them get rid of the commas....

....in answer to your comment here is one possible way to do it. Taking a sample from the json data in your question:

 var data = [
    {
        "address": "0xde083e40fe84835cbbd6c69f6595cae1e85551dc",
        "name": "Ledger Legend Cards",
        "symbol": "LLC",
        "image_url": "https://storage.googleapis.com/opensea-static/ledgerlegends-logo.png",
        "featured_image_url": null,
        "featured": false,
        "description": "Ledger Legends is an early access collectible card game built on the Ethereum platform. It uses the new ERC721 non-fungible token standard to track its cards. Using this standard makes it easy for the cards to integrate into the wider Ethereum ecosystem, like exchanges and wallets. Being a card game that is built using smart contracts you know that your cards will always be owned by you and can never be taken away by anyone unlike centralized games such as Hearthstone.",
        "external_link": "https://ledgerlegends.com/",
        "wiki_link": null,
        "stats": {
            "seven_day_volume": 0,
            "seven_day_change": 0,
            "total_volume": 0,
            "count": 282,
            "num_owners": 54,
            "market_cap": 0,
            "average_price": 0,
            "items_sold": 0
        },
        "traits": [
            {
                "FN.RA.NA": "Value A",
                "RR.TT.DD": "Value B",
            },
            {
                "FN.RA.NA": "Value A",
                "RR.TT.DD": "Value B",
            },
            {
                "FN.RA.NA": "Value A",
                "RR.TT.DD": "Value B",
            },
            {
                "FN.RA.NA": "Value A",
                "RR.TT.DD": "Value B",
                "MORE.MORE.MORE": [
                    {
                        "FN.RA.NA": "Value A",
                        "RR.TT.DD": "Value B",
                    },
                    {
                        "FN.RA.NA": "Value A",
                        "RR.TT.DD": "Value B",
                    },
                    {
                        "FN.RA.NA": "Value A",
                        "RR.TT.DD": "Value B",
                    },
                    {
                        "FN.RA.NA": "Value A",
                        "RR.TT.DD": "Value B",
                    }
                ]
            }
        ],
        "hidden": true,
        "nft_version": "1.0",
        "schema_name": "ERC721",
        "display_data": {
            "images": [
                "https://ledgerlegends.com/img/monster.png",
                "https://ledgerlegends.com/img/monster.png",
                "https://ledgerlegends.com/img/monster.png",
                "https://ledgerlegends.com/img/monster.png",
                "https://ledgerlegends.com/img/monster.png",
                "https://ledgerlegends.com/img/monster.png"
            ]
        },
        "short_description": null,
        "total_supply": null,
        "owner": null,
        "buyer_fee_basis_points": 0,
        "seller_fee_basis_points": 250
    }

];

//is it an object
function isObject(o) {
    return Object.prototype.toString.call(o) === "[object Object]";
}
//is it an array
function isArray(o) {
    return Array.isArray(o);
}
//clean the keys and take advantage of the reference to the original 
    //object to re write and replace the keys and their values
    function cleanKeys(o) {
        var keys = Object.keys(o);
        for (var i = 0; i < keys.length; i++) {
            var key = keys[i];
            var toCheck = o[key];
            var originalKey = key;
            //if there is a dot in the key
            //re write it and replace it
            if (key.indexOf('.') > -1) {
                key = key.split(".").join(",");
                o[key] = o[originalKey];
                delete o[originalKey];
            }
            if (isArray(toCheck) || isObject(toCheck)) {
                removeDots(toCheck);
            }
        }
    }
//a somewhat recursive function with bits broken out for readability 
function removeDots(obj) {
    switch (Object.prototype.toString.call(obj)) {
        case "[object Array]":
            for (var i = 0; i < obj.length; i++) {
                var o = obj[i];
                if (isArray(o)) {
                    removeDots(obj);
                } else {
                    cleanKeys(o);
                }
            }
            break;
        case "[object Object]":
            cleanKeys(obj);
            break;
    }
}
removeDots(data);


console.log(JSON.stringify(data, null, 2));



 [
  {
    "address": "0xde083e40fe84835cbbd6c69f6595cae1e85551dc",
    "name": "Ledger Legend Cards",
    "symbol": "LLC",
    "image_url": "https://storage.googleapis.com/opensea-static/ledgerlegends-logo.png",
    "featured_image_url": null,
    "featured": false,
    "description": "Ledger Legends is an early access collectible card game built on the Ethereum platform. It uses the new ERC721 non-fungible token standard to track its cards. Using this standard makes it easy for the cards to integrate into the wider Ethereum ecosystem, like exchanges and wallets. Being a card game that is built using smart contracts you know that your cards will always be owned by you and can never be taken away by anyone unlike centralized games such as Hearthstone.",
    "external_link": "https://ledgerlegends.com/",
    "wiki_link": null,
    "stats": {
      "seven_day_volume": 0,
      "seven_day_change": 0,
      "total_volume": 0,
      "count": 282,
      "num_owners": 54,
      "market_cap": 0,
      "average_price": 0,
      "items_sold": 0
    },
    "traits": [
      {
        "FN,RA,NA": "Value A",
        "RR,TT,DD": "Value B"
      },
      {
        "FN,RA,NA": "Value A",
        "RR,TT,DD": "Value B"
      },
      {
        "FN,RA,NA": "Value A",
        "RR,TT,DD": "Value B"
      },
      {
        "FN,RA,NA": "Value A",
        "RR,TT,DD": "Value B",
        "MORE,MORE,MORE": [
          {
            "FN,RA,NA": "Value A",
            "RR,TT,DD": "Value B"
          },
          {
            "FN,RA,NA": "Value A",
            "RR,TT,DD": "Value B"
          },
          {
            "FN,RA,NA": "Value A",
            "RR,TT,DD": "Value B"
          },
          {
            "FN,RA,NA": "Value A",
            "RR,TT,DD": "Value B"
          }
        ]
      }
    ],
    "hidden": true,
    "nft_version": "1.0",
    "schema_name": "ERC721",
    "display_data": {
      "images": [
        "https://ledgerlegends.com/img/monster.png",
        "https://ledgerlegends.com/img/monster.png",
        "https://ledgerlegends.com/img/monster.png",
        "https://ledgerlegends.com/img/monster.png",
        "https://ledgerlegends.com/img/monster.png",
        "https://ledgerlegends.com/img/monster.png"
      ]
    },
    "short_description": null,
    "total_supply": null,
    "owner": null,
    "buyer_fee_basis_points": 0,
    "seller_fee_basis_points": 250
  }
]

maybe

data[i].traits = Object.entries(data[i].traits).reduce((memo, [key, value]) => {
  memo[key.replace(/./g, ',')] = value;
  return memo;
}, {});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM