2017-11-03 2 views
2

Ich habe eine ArtWeglassen Nichts/null Felder in Haskell Aeson

{-# LANGUAGE DeriveGeneric #-} 
{-# LANGUAGE TemplateHaskell #-} 
{-# LANGUAGE MultiWayIf  #-} 

import GHC.Generics 
import Data.Aeson.TH 
import Data.Aeson.Types 

data MyJSONObject = MyJSONObject 
    { name :: String 
    , ptype :: Maybe String 
    , pid  :: Maybe String 
    , subject :: Maybe String 
    , message :: Maybe String 
    } deriving (Show, Generic) 

mit sehr vielen mehr Maybe String Felder aus. Meine FromJSON und ToJSON durch die TemplateHaskell Funktion zur Verfügung gestellt werden

$(deriveJSON defaultOptions 
    { 
    omitNothingFields = True 
    , fieldLabelModifier = \f -> if 
     | f == "ptype" -> "type" -- reserved keyword 
     | f == "pid" -> "id" -- Prelude function name 
     | otherwise -> f 
    } ''MyJSONObject) 

Letztlich ist die Ausgabe des Programms ist ein JSON Dokument gedacht von einer Anwendung verbraucht werden, die Nullwerte nicht über einige Felder zulassen, auch wenn es tut erlauben Sie, dass diese Felder nicht existieren. Mit anderen Worten, es ist völlig in Ordnung, dass subject im JSON-Dokument nicht vorhanden ist, aber wenn es existiert, kann sein Wert nicht null sein. Meine Erwartung war, dass omitNothingFields würde diese Anforderung behandeln, aber dies scheint nicht der Fall zu sein: die decode d JSON hat noch Nothing Werte für Felder, die nicht vorhanden sind, und encode d JSON hat null Werte für diese Felder. Der erste Fall ist in Ordnung; Letzteres ist nicht die Frage.

Verwechsle ich oder missverstanden den Zweck von, omitNothingFields? Wie kann ich Felder mit Nothing/null Werten ignorieren?

+1

Funktioniert für mich. ('encode (MyJSONObject" foo "Nichts Nichts Nichts Nichts)' Gibt '" {\ "Name \": \ "foo \"} "'.) Welche Version von Aeson benutzt Du? –

+0

@DanielWagner Ich benutze 'Aeson-1.1.2.0'. Mein Problem stellte sich heraus, dass ich 'FromJSON/ToJSON' nicht für' data MyOtherJSONObject = MyOtherJSONObject {objects :: [MyJSONObject]} abgeleitet habe (Show, Generic) '(das sind die Daten, die _really_' decode'/'encode' haben wollten) mit der Option 'omitNothingFields'. Warum ich es auch dort brauchte, ist mir ein Rätsel. Ich dachte, mein Problem beträfe die 'MyJSONObject'-Instanzen. – user4601931

Antwort

5

Funktioniert für mich. Versuchen Sie, Generics statt TH zu verwenden. Vielleicht macht es das.

*Main Data.Aeson> decode "{\"name\":\"str\"}" :: Maybe MyJSONObject 
Just (MyJSONObject {name = "str", ptype = Nothing, pid = Nothing, subject = Nothing, message = Nothing}) 
*Main Data.Aeson> encode (MyJSONObject "str" Nothing Nothing Nothing Nothing) 
"{\"name\":\"str\"}" 

Der vollständige Code ist

{-# LANGUAGE DeriveGeneric #-} 
import GHC.Generics 
import Data.Aeson 
import Data.Aeson.Types 

data MyJSONObject = MyJSONObject 
    { name :: String 
    , ptype :: Maybe String 
    , pid  :: Maybe String 
    , subject :: Maybe String 
    , message :: Maybe String 
    } deriving (Show, Generic) 

instance ToJSON MyJSONObject where 
    toJSON = genericToJSON defaultOptions 
    { omitNothingFields = True } 

instance FromJSON MyJSONObject where 
    parseJSON = genericParseJSON defaultOptions 
    { omitNothingFields = True } 

GHC Mit 8.2.1, aeson-1.1.2.0.

+0

Danke für Ihre Antwort. Um genauer zu sein, definiere ich später 'data MyOtherJSONObject = MyOtherJSONObject {objects :: [MyJSONObject]} abgeleitet (Show, Generic)' und es ist dieses Objekt, das ich Nothing/null auslassen möchte. Offensichtlich musste ich auch die Option "omitNothingFields" in diese Instanz einfügen. Warum ich das tun musste, bin ich mir nicht so sicher. Es ist immer noch so, dass "decode" eine Menge Nothing-Werte zurückgibt, aber wie ich schon sagte, das ist weniger wichtig für mich. Danke noch einmal. – user4601931

Verwandte Themen