问题描述
我正在使用this function,需要将其传递给Aeson Value
:
{ logLevel : vega.Debug }
这应该是指绑定不会导出的javascript程序包中的enum。
为此,我应该使用Data.Aeson.QQ.Simple
,但是我尝试编译的所有内容都会在"vega.Debug"
周围加上引号,而我却没有。
[aesonQQ| { logLevel : "vega.Debug" } |]
我想念什么?有没有办法使用encode?
解决方法
通常,Aeson Value
仅表示JSON对象,因此它们不支持嵌入式JavaScript表达式或任何其他扩展。
如果此API仅接受 Value
个,则您将陷入困境。我认为 best 的解决方案是仅复制vega.Debug
的整数值并将其序列化。
否则,一个简单的解决方案是制作toHtmlWith
的修改版本,以接受更灵活的输入类型,例如字符串:
toHtmlWith' :: Maybe Text -> VegaLite -> Text
toHtmlWith' mopts vl =
let spec = encodeToLazyText (fromVL vl)
-- NB: Removed ‘encodeToLazyText’ call here.
opts = maybe "" (\o -> "," <> o) mopts
in TL.unlines
[ "<!DOCTYPE html>","<html>","<head>"
-- versions are fixed at vega 5,vega-lite 4," <script src=\"https://cdn.jsdelivr.net/npm/vega@5\"></script>"," <script src=\"https://cdn.jsdelivr.net/npm/vega-lite@4\"></script>"," <script src=\"https://cdn.jsdelivr.net/npm/vega-embed\"></script>","</head>","<body>","<div id=\"vis\"></div>","<script type=\"text/javascript\">"," var spec = " <> spec <> ";"," vegaEmbed(\'#vis\',spec" <> opts <> ").then(function(result) {"," // Access the Vega view instance (https://vega.github.io/vega/docs/api/view/) as result.view"," }).catch(console.error);","</script>","</body>","</html>"
]
然后,您可以根据自己的Aeson值调用encodeToLazyText
,或根据需要包含任意Text
字符串。
如果您确实要避免重复页面内容,那么您也可以调用现有的toHtmlWith
和Value
,其中包含您控制的特殊分隔符,例如String "<user1441998>vega.Debug</user1441998>"
,然后使用该定界符对结果进行后处理:
unquoteHackSplices = replace "\"<user1441998>" ""
. replace "</user1441998>\"" ""
有没有办法使用编码?
作为另一种技巧,您可以为您的类型创建一个ToJSON
实例,该实例实现toEncoding
但不是 toJSON
,并且编码值是JavaScript表达式(即无效的JSON)。您可能希望使toJSON
出现错误,以免您无意中使用它。
如果您想生成一般的JavaScript代码,请看language-javascript
。代替产生Value
,而是产生JSExpression
,然后使用像renderToText
这样的漂亮打印功能之一来渲染它。这是一个可能的解决方案的结构草图:
-- Like ‘ToJSON’ but may produce arbitrary JavaScript expressions
class ToJavaScript a where
toJavaScript :: a -> JSExpression
-- Helper function to convert from Aeson Value
jsFromJson :: Value -> JSExpression
jsFromJson v = case v of
Object o -> JSObjectLiteral …
Array a -> JSArrayLiteral …
String s -> JSStringLiteral …
…
instance ToJavaScript YourType where
toJavaScript = …
rendered :: Text
rendered = renderToText
$ JSAstExpression (toJavaScript yourValue) JSNoAnnot
您的表达式将采用以下格式:
JSMemberDot
(JSIdentifier JSNoAnnot "vega")
JSNoAnnot
(JSIdentifier JSNoAnnot "Debug")
JSAnnot
类型还允许您在生成的结果中包括注释。请记住,与Aeson的JSON序列化相比,language-javascript
的精美印刷可能没有得到很好的优化。