Bao bọc tất cả các số trong JSON bằng dấu ngoặc kép


10

Có dữ liệu JSON chứa một số giá trị số. Làm thế nào để chuyển đổi tất cả các số sang chuỗi? (gói bằng dấu ngoặc kép)

Thí dụ:

{
        "id":1,
        "customer":"user",
        "plate":"BMT-216-A",
        "country":"GB",
        "amount":1000,
        "pndNumber":20000,
        "zoneNumber":4
}

nên trở thành

{
        "id":"1",
        "customer":"user",
        "plate":"BMT-216-A",
        "country":"GB",
        "amount":"1000",
        "pndNumber":"20000",
        "zoneNumber":"4"
}

Câu trả lời:


28
$ jq 'map_values(tostring)' file.json
{
  "id": "1",
  "customer": "user",
  "plate": "BMT-216-A",
  "country": "GB",
  "amount": "1000",
  "pndNumber": "20000",
  "zoneNumber": "4"
}

Chuyển hướng đến một tệp mới và sau đó di chuyển nó đến tên tệp gốc.

Để chuyển đổi kỹ lưỡng hơn các số trong cấu trúc không phẳng thành chuỗi, hãy xem xét

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

Điều này sẽ kiểm tra mọi giá trị đệ quy trong tài liệu đã cho và chọn những giá trị là số. Các giá trị được chọn sau đó được chuyển đổi thành chuỗi. Nói một cách chính xác, nó cũng sẽ nhìn vào các khóa, nhưng vì đây không phải là số đơn giản trong JSON, nên sẽ không có khóa nào được chọn.

Thí dụ:

$ jq . file.json
{
  "a": {
    "b": 1
  },
  "b": null,
  "c": [
    1,
    2,
    "hello",
    4
  ]
}
$ jq '(..|select(type == "number")) |= tostring' file.json
{
  "a": {
    "b": "1"
  },
  "b": null,
  "c": [
    "1",
    "2",
    "hello",
    "4"
  ]
}

Ngoài ra, trích dẫn null, thay đổi select()thành

select(type == "number" or type == "null")

3
Lưu ý rằng nó thay đổi {"a":{"b":1},"b":null}thành{ "a": "{\"b\":1}", "b": "null" }
Stéphane Chazelas

@ StéphaneChazelas Vâng, nó sẽ biến các đối tượng phụ thành chuỗi. Cấu trúc dữ liệu đã cho tuy nhiên không chứa các đối tượng phụ.
Kusalananda

2
Không chỉ các đối tượng phụ, tất cả các giá trị bao gồm mảng, booleans và null(vẫn đáng chú ý IMO mặc dù mẫu của OP không có giá trị nào trong số đó).
Stéphane Chazelas

Và làm thế nào để thay đổi điều này nếu tôi có một mảng?
VK

@ StéphaneChazelas Sắp xếp. Cảm ơn đã chọc tôi.
Kusalananda

8

Đây là một giải pháp dễ dàng dựa trên jtctiện ích unix:

bash $ jtc -w'<.*>D:' -eu echo '"{}"' \; file.json
{
   "amount": "1000",
   "country": "GB",
   "customer": "user",
   "id": "1",
   "plate": "BMT-216-A",
   "pndNumber": "20000",
   "zoneNumber": "4"
}
bash $ 

nếu bạn muốn áp dụng các thay đổi ngay vào tệp json, hãy sử dụng công -ftắc, như thế này:

bash $ jtc -f -w'<.*>D:' -eu echo '"{}"' \; file.json

Giải pháp đề xuất sẽ hoạt động chính xác với một jsons có cấu trúc tùy ý, ví dụ:

bash $ jtc -w'<.*>D:' -eu echo '"{}"' \; file.json
{
   "amount": "1000",
   "country": "GB",
   "customer": "user",
   "id": "1",
   "plate": "BMT-216-A",
   "pndNumber": "20000",
   "sub": {
      "subvalue": "123"
   },
   "zoneNumber": "4"
}
bash $ 
  • nếu bạn muốn trích dẫn các giá trị null, chỉ cần ném vào một lối đi -w'<>n:'
  • nếu bạn muốn trích dẫn các giá trị boolean, hãy đi bộ -w'<any>b:'

Ngoài ra, tác vụ đảo ngược (bỏ tất cả các số) có thể dễ dàng đạt được theo cách tương tự: giả sử, file.jsonđã được "liệt kê", để bỏ qua tất cả các số:

bash $ jtc -w'<^\d+$>R:' -eu echo {-} \; file.json
{
   "amount": 1000,
   "country": "GB",
   "customer": "user",
   "id": 1,
   "plate": "BMT-216-A",
   "pndNumber": 20000,
   "zoneNumber": 4
}
bash $ 

CẬP NHẬT : phiên bản mới nhất của jtcthực hiện bây giờ các mẫu và không gian tên. Với điều đó, không yêu cầu vỏ bên ngoài được yêu cầu:

bash $ jtc -w'<.*>D:' -u'<.*>D:<val>v' -T'"{val}"' file.json
{
   "amount": "1000",
   "country": "GB",
   "customer": "user",
   "id": "1",
   "plate": "BMT-216-A",
   "pndNumber": "20000",
   "zoneNumber": "4"
}

jtchướng dẫn sử dụng: https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md


4
perl -pe 's/("(?:\\.|[^"])*")|[^\s[\]{}:,"]+/$1||qq("$&")/ge' file.json

Sẽ trích dẫn bất cứ điều gì không được trích dẫn và không []{}:,whitespace, vì vậy sẽ trích dẫn số true, falsenull.

perl -pe 's/("(?:\\.|[^"])*")|-?\d+(?:\.\d+)?(?:[eE][-+]?\d+)?/$1||qq("$&")/ge'

Sẽ trích dẫn cụ thể những gì phù hợp với đặc điểm kỹ thuật của một số json và đó không phải là trong dấu ngoặc kép.

Những người thực hiện mã thông báo chính xác dựa trên đặc tả JSON, đó không phải là một xấp xỉ.


-1

Tôi đã thử với phương pháp dưới đây và nó hoạt động tốt.

Tôi đã cố gắng 2 lần để cố gắng giảm mức độ của mình

Chỉ huy:

sed 's/[0-9]\{1,\},\?$/"&/g' filename |
sed '/[0-9]\{1,\}$/s/[0-9]\{1,\}/&"/g'|
sed '/[0-9]\{1,\},$/s/,$/"&/g`'

Đầu ra:

 {
        "id":"1",
        "customer":"user",
        "plate":"BMT-216-A",
        "country":"GB",
        "amount":"1000",
        "pndNumber":"20000",
        "zoneNumber":"4"
}

@Kusalananda đã sửa mã
Praveen Kumar BS

tại sao bạn sử dụng \{1,\},? Để kiểm tra xem một phần tử xuất hiện một hay nhiều lần sử dụng +. Và điều này sẽ không hoạt động đối với các số như -123, 0xab, 0o12, 0b1011, 1e23 hoặc 1.2e3 ...
phuclv

@phuclv \{1,\}là tương đương BRE của ERE +. Một số sedtriển khai hỗ trợ \+dưới dạng tiện ích mở rộng -Ehoặc -rtùy chọn để bật ERE nhưng không khả dụng. \?là một tiện ích mở rộng không di động khác mặc dù có tiêu chuẩn tương đương\{0,1\}
Stéphane Chazelas

@phuclv bạn sẽ không tìm thấy các số 0xab 0o12 0b1011 không được trích dẫn trong tệp JSON hợp lệ.
Stéphane Chazelas
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.