ล้อมตัวเลขทั้งหมดใน JSON ด้วยเครื่องหมายคำพูด


11

มีข้อมูล JSON ซึ่งมีค่าตัวเลขบางค่า จะแปลงตัวเลขทั้งหมดเป็นสตริงได้อย่างไร? (ห่อด้วยคำพูด)

ตัวอย่าง:

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

ควรกลายเป็น

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

คำตอบ:


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

เปลี่ยนเส้นทางไปยังไฟล์ใหม่แล้วย้ายไปยังชื่อไฟล์เดิม

สำหรับการแปลงตัวเลขในโครงสร้างที่ไม่ใช่แบบแบนให้เป็นสตริงให้ละเอียดยิ่งขึ้น

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

สิ่งนี้จะตรวจสอบทุกค่าที่เกิดซ้ำในเอกสารที่กำหนดและเลือกค่าที่เป็นตัวเลข ค่าที่เลือกจะถูกแปลงเป็นสตริง มันจะพูดอย่างเคร่งครัดดูที่กุญแจ แต่เนื่องจากตัวเลขเหล่านี้ไม่สามารถเป็นตัวเลขธรรมดาใน JSON จึงไม่มีการเลือกคีย์

ตัวอย่าง:

$ 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"
  ]
}

นอกจากนี้ในการพูดnullเปลี่ยนselect()ไป

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

3
โปรดทราบว่ามันเปลี่ยน{"a":{"b":1},"b":null}เป็น{ "a": "{\"b\":1}", "b": "null" }
Stéphane Chazelas

@ StéphaneChazelasใช่มันจะเปลี่ยนวัตถุย่อยเป็นสตริง โครงสร้างข้อมูลที่กำหนดไม่ได้มีวัตถุย่อย
Kusalananda

2
ไม่เพียง แต่วัตถุย่อยเท่านั้นค่าทั้งหมดรวมถึงอาร์เรย์บูลีนและnull(ยังคงมีค่าที่จะสังเกตเห็น IMO แม้ว่าตัวอย่างของ OP จะไม่มีสิ่งเหล่านั้น)
Stéphane Chazelas

และวิธีการเปลี่ยนนี้ถ้าฉันมีอาร์เรย์?
VK

จัดเรียง @ StéphaneChazelas ขอบคุณสำหรับ poking ที่ฉัน
Kusalananda

8

นี่เป็นวิธีที่ง่ายขึ้นอยู่กับjtcยูทิลิตี้ยูนิกซ์:

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 $ 

หากคุณต้องการใช้การเปลี่ยนแปลงในไฟล์ json ให้ใช้-fสวิตช์ดังนี้:

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

โซลูชันที่เสนอจะทำงานอย่างถูกต้องกับ jsons ที่มีโครงสร้างตามอำเภอใจเช่น:

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 $ 
  • ถ้าคุณชอบที่จะพูดค่า null เพียงแค่โยนในเส้นทางเดิน -w'<>n:'
  • ถ้าคุณชอบที่จะพูดค่าบูลีนโยนในเส้นทางเดิน -w'<any>b:'

นอกจากนี้งานย้อนกลับ (unquote ตัวเลขทั้งหมด) สามารถทำได้ง่ายในลักษณะที่คล้ายกัน: พูดว่าfile.jsonมีอยู่แล้ว "enquoted" เพื่อยกเลิกการอ้างถึงตัวเลขทั้งหมด:

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 $ 

อัปเดต : เวอร์ชันล่าสุดของjtcการดำเนินการในขณะนี้เทมเพลตและเนมสเปซ เมื่อไม่ต้องการการเรียกใช้เปลือกภายนอก:

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"
}

jtcคู่มือผู้ใช้: https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md


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

จะพูดอะไรที่ไม่ได้ยกมาและไม่ได้เป็น[]{}:,whitespaceดังนั้นจะพูดตัวเลขtrue, และfalsenull

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

จะอ้างเฉพาะสิ่งที่ตรงกับข้อกำหนดของหมายเลข json และที่ไม่ได้อยู่ในคำพูด

โทเค็นเหล่านั้นมีความถูกต้องตามข้อมูลจำเพาะของ JSON ไม่ใช่การประมาณ


-1

ฉันลองด้วยวิธีการด้านล่างและทำงานได้ดี

ฉันไปป์ไลน์ถึง 2 ครั้งพยายามลดระดับลง

คำสั่ง:

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

เอาท์พุท:

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

@Kusalananda แก้ไขรหัส
Praveen Kumar BS

ทำไมคุณใช้\{1,\},? +เพื่อทดสอบว่าเป็นองค์ประกอบที่ปรากฏขึ้นหนึ่งครั้งหรือมากกว่าการใช้งาน และสิ่งนี้จะไม่ทำงานกับตัวเลขเช่น -123, 0xab, 0o12, 0b1011, 1e23 หรือ 1.2e3 ...
phuclv

@phuclv \{1,\}เป็นเทียบเท่า BRE ของ +ERE บางsedการใช้งานที่ให้การสนับสนุน\+เป็นส่วนขยายหรือ-Eหรือ-rตัวเลือกที่จะเปิดใช้งาน Eres แต่ที่ไม่พกพา \?เป็นส่วนขยายอื่นที่ไม่ใช่แบบพกพาแม้ว่าจะมีค่าเทียบเท่ามาตรฐาน\{0,1\}
Stéphane Chazelas

@phuclv คุณจะไม่พบหมายเลข unquoted 0xab 0o12 0b1011 ในไฟล์ JSON ที่ถูกต้อง
Stéphane Chazelas
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.