Пример того, как анализировать вывод 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 ...перед выполнением строк в ответе дона. - 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