Shell JSON – How to Drop Decimal Places in JSON Array

floating pointjsonshell

What shell command in a bash script could be issued to efficiently strip all the decimal places from the numbers in a JSON file such as this:

    [
        {
            "IMSKU": "1000001", 
            "AttributeID": 7332.0, 
            "Value": "McAfee Host Intrusion Prevention for Desktops safeguards your business against complex security threats that may otherwise be unintentionally introduced or allowed by desktops and laptops. Host Intrusion Prevention for Desktops is easy to deploy, configure, and manage.", 
            "Unit": null, 
            "StoredValue": null, 
            "StoredUnit": null, 
            "Name": "Marketing text", 
            "Format": "1", 
            "Position": "1", 
            "Group_Name": "Basic Specification", 
            "AGGroup_Position": 0.0, 
            "Product_Hierarchy": 15198001453.0
        }, 
        {
            "IMSKU": "1000001", 
            "AttributeID": 7343.0, 
            "Value": "May 2013", 
            "Unit": null, 
            "StoredValue": null, 
            "StoredUnit": null, 
            "Name": "PI Date", 
            "Format": "1", 
            "Position": "1", 
            "Group_Name": "PI DATE", 
            "AGGroup_Position": 1.0, 
            "Product_Hierarchy": 15198001453.0
        }, 
        {
            "IMSKU": "1000001", 
            "AttributeID": 7344.0, 
            "Value": "McAfee", 
            "Unit": null, 
            "StoredValue": "0.00", 
            "StoredUnit": null, 
            "Name": "Brand Name", 
            "Format": "3", 
            "Position": "1", 
            "Group_Name": "PRODUCT", 
            "AGGroup_Position": 2.0, 
            "Product_Hierarchy": 15198001453.0
        }
    ]

So that

"AttributeID":  7344.0

would become

"AttributeID":  7344

for example, and so forth.

Best Answer

Just running it through the identity filter with jq reformats the numbers that has a .0 decimal as integers:

$ jq . file.json
[
  {
    "IMSKU": "1000001",
    "AttributeID": 7332,
    "Value": "McAfee Host Intrusion Prevention for Desktops safeguards your business against complex security threats that may otherwise be unintentionally introduced or allowed by desktops and laptops. Host Intrusion Prevention for Desktops is easy to deploy, configure, and manage.",
    "Unit": null,
    "StoredValue": null,
    "StoredUnit": null,
    "Name": "Marketing text",
    "Format": "1",
    "Position": "1",
    "Group_Name": "Basic Specification",
    "AGGroup_Position": 0,
    "Product_Hierarchy": 15198001453
  },

(etc.)

If there are numbers with decimals that are not zero, and you want to remove these too, use

jq '(.. | select(type == "number" )) |= floor' file.json

This would apply the floor function on all numbers whatsoever in the data, rounding them down to the closest integer.

To also investigate whether there are strings that contain digits after a dot at the very end, and remove these digits (and the dot):

jq '(.. | select(type == "string")) |= sub("\\.[0-9]+$"; "")' file.json

The affected entries would still be strings and are not converted to a numerical type.

Related Question