Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/email/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Json 使用Aeson';将产品类型编码为对象,而不是列表_Json_Haskell_Aeson - Fatal编程技术网

Json 使用Aeson';将产品类型编码为对象,而不是列表

Json 使用Aeson';将产品类型编码为对象,而不是列表,json,haskell,aeson,Json,Haskell,Aeson,在以下代码中,encoded等于{“FooBar”:[{“Bar”:4},{“Baz”:2}} 所需的编码是{“FooBar”:{“Bar”:4,“Baz”:2} import Data.Aeson import Data.Aeson.Types data Foo = FooBar Bar Baz deriving Generic newtype Bar = Bar Integer deriving Generic newtype Baz = Baz

在以下代码中,
encoded
等于
{“FooBar”:[{“Bar”:4},{“Baz”:2}}

所需的编码是
{“FooBar”:{“Bar”:4,“Baz”:2}

import           Data.Aeson
import           Data.Aeson.Types

data Foo = FooBar Bar Baz deriving Generic

newtype Bar = Bar Integer deriving Generic

newtype Baz = Baz Integer deriving Generic

instance ToJSON Foo where
  toJSON = genericToJSON options

instance ToJSON Bar where
  toJSON = genericToJSON options

instance ToJSON Baz where
  toJSON = genericToJSON options

options :: Options
options = defaultOptions { tagSingleConstructors = True, 
                           sumEncoding = ObjectWithSingleField }

foo :: Foo
foo = FooBar (Bar 4) (Baz 2)

encoded = encode foo
也就是说,我希望产品类型的构造函数是键,它们的组件是对象。我已经能够非常接近
tagSingleConstructors=True
sumcodencing=ObjectWithSingleField
,但是Aeson将
Bar
Baz
放在一个列表中,而不是一个对象中


Options
中的其他修饰符似乎都不相关,但我可能遗漏了什么。使用
genericToJSON
是否可以进行所需的编码?

使用记录语法可以获得所需的结果。 在这种情况下,Aeson将值编码为对象。 但是,在这种情况下需要两组选项,一组用于
FooBar
,另一组用于
Foo
Bar

data Foo = FooBar { bar:: Bar, baz :: Baz} deriving Generic

data Bar = Bar Integer deriving Generic

newtype Baz = Baz Integer deriving Generic
instance ToJSON Foo where
  toJSON = genericToJSON options

instance ToJSON Bar where
  toJSON = genericToJSON option_nested

instance ToJSON Baz where
  toJSON = genericToJSON option_nested

options :: Options
options = defaultOptions { tagSingleConstructors = True,
                           sumEncoding = ObjectWithSingleField,
                           fieldLabelModifier = \s -> (toUpper . head) s : (tail s)  }
option_nested :: Options
option_nested = defaultOptions { sumEncoding = UntaggedValue }

结果:
{“FooBar”:{“Baz”:2,“Bar”:4}}“

如果您有一个产品类型的总和类型会怎么样?我假设每个产品类型都可以是一个记录,但是如果在错误的产品类型上使用,您会有部分访问器,这将引发运行时错误。e.x.
数据Foo=Bar{x::String}Baz{y::String}
x$Baz“Foo”“
不会抛出任何编译时警告/错误,但会导致运行时错误。当您有一个乘积和时,这就为不使用记录提供了有力的理由。