ตัวอย่างวิธีแยกวิเคราะห์เอาต์พุต exiftool JSON ใน Haskell

ฉันไม่สามารถเข้าใจเอกสารใดๆ ได้ ใครช่วยกรุณายกตัวอย่างว่าฉันสามารถแยกวิเคราะห์เอาต์พุต exiftool แบบสั้นต่อไปนี้โดยใช้โมดูล Haskell Text.JSON ได้อย่างไร ข้อมูลกำลังสร้างโดยใช้คำสั่ง exiftool -G -j <files.jpg>

[{
  "SourceFile": "DSC00690.JPG",
  "ExifTool:ExifToolVersion": 7.82,
  "File:FileName": "DSC00690.JPG",
  "Composite:LightValue": 11.6
},
{
  "SourceFile": "DSC00693.JPG",
  "ExifTool:ExifToolVersion": 7.82,
  "File:FileName": "DSC00693.JPG",
  "EXIF:Compression": "JPEG (old-style)",
  "EXIF:ThumbnailLength": 4817,
  "Composite:LightValue": 13.0
},
{
  "SourceFile": "DSC00694.JPG",
  "ExifTool:ExifToolVersion": 7.82,
  "File:FileName": "DSC00694.JPG",
  "Composite:LightValue": 3.7
}]

person me2    schedule 18.01.2010    source แหล่งที่มา


คำตอบ (2)


วิธีที่ง่ายที่สุดคือการคืน JSValue จากแพ็คเกจ json เช่นนั้น (สมมติว่า ข้อมูลของคุณอยู่ใน text.json):

Prelude Text.JSON> s <- readFile "test.json"
Prelude Text.JSON> decode s :: Result JSValue
Ok (JSArray [JSObject (JSONObject {fromJSObject = [("SourceFile",JSString (JSONString {fromJSString = "DSC00690.JPG"})),("ExifTool:ExifToolVersion",JSRational False (391 % 50)),("File:FileName",JSString (JSONString {fromJSString = "DSC00690.JPG"})),("Composite:LightValue",JSRational False (58 % 5))]}),JSObject (JSONObject {fromJSObject = [("SourceFile",JSString (JSONString {fromJSString = "DSC00693.JPG"})),("ExifTool:ExifToolVersion",JSRational False (391 % 50)),("File:FileName",JSString (JSONString {fromJSString = "DSC00693.JPG"})),("EXIF:Compression",JSString (JSONString {fromJSString = "JPEG (old-style)"})),("EXIF:ThumbnailLength",JSRational False (4817 % 1)),("Composite:LightValue",JSRational False (13 % 1))]}),JSObject (JSONObject {fromJSObject = [("SourceFile",JSString (JSONString {fromJSString = "DSC00694.JPG"})),("ExifTool:ExifToolVersion",JSRational False (391 % 50)),("File:FileName",JSString (JSONString {fromJSString = "DSC00694.JPG"})),("Composite:LightValue",JSRational False (37 % 10))]})])

นี่เป็นเพียงการให้ประเภทข้อมูล json Haskell ทั่วไปแก่คุณ

ขั้นตอนต่อไปคือการกำหนดประเภทข้อมูล Haskell ที่กำหนดเองสำหรับข้อมูลของคุณ และเขียนอินสแตนซ์ของ JSON สำหรับสิ่งนั้น ซึ่งจะแปลงระหว่าง JSValue ดังที่กล่าวข้างต้นกับประเภทของคุณ

person Don Stewart    schedule 18.01.2010
comment
เดิมทีฉันโพสต์คำตอบแยกต่างหากในช่วงเวลาเดียวกัน แต่ฉันพบว่าฉันชอบถ้อยคำในข้อนี้มากกว่า... โอ้เอาล่ะ ฉันจะเพิ่ม€ 0.02 เป็นความคิดเห็น: ดูไฟล์ Text/JSON.hs ในแหล่งที่มาของ json-the-package มีอินสแตนซ์ JSON แบบง่าย ๆ มากมายที่กำหนดไว้ที่นั่น และสามารถใช้เป็นตัวอย่างที่มีประโยชน์ได้ - person Michał Marczyk; 19.01.2010
comment
คำตอบที่ดี! ฉันคาดหวังอะไรจากผู้ร่วมเขียน 'Real World Haskell' อีกครั้ง (book.realworldhaskell.org) ซึ่งเป็นหนังสือที่เจ๋งจริงๆ - person Robert Massaioli; 24.05.2010
comment
สำหรับมือใหม่ คุณจะต้องทำ Prelude>:m +Text.JSON ...ก่อนที่จะดำเนินการบรรทัดในการตอบกลับของ dons - person ramanujan; 12.12.2010

ขอบคุณทุกคน. จากข้อเสนอแนะของคุณ ฉันสามารถรวบรวมสิ่งต่อไปนี้ซึ่งแปล JSON กลับเป็นคู่ชื่อ-ค่า

data Exif = 
    Exif [(String, String)]
    deriving (Eq, Ord, Show)

instance JSON Exif where
    showJSON (Exif xs) = showJSONs xs
    readJSON (JSObject obj) = Ok $ Exif [(n, s v) | (n, JSString v) <- o]
        where 
            o = fromJSObject obj
            s = fromJSString

น่าเสียดายที่ดูเหมือนว่าไลบรารีไม่สามารถแปล JSON กลับเป็นโครงสร้างข้อมูล Haskell แบบธรรมดาได้โดยตรง ใน Python มันเป็นซับเดียว: json.loads(s)

person me2    schedule 19.01.2010
comment
ก็ต้องพิมพ์แบบคงที่ ดังนั้น Haskell จึงสร้างประเภท JSValue แบบง่าย ๆ ซึ่งคุณสามารถใช้งานได้โดยตรงหากต้องการ ประโยชน์ของการใช้ Haskell คือการตรวจสอบคงที่เพิ่มเติมที่คุณจะได้รับหากคุณสร้างโครงสร้างเฉพาะในทางกลับกัน - person Don Stewart; 19.01.2010