如何使用Aeson生成文字未加引号的javascript表达式?

问题描述

我正在使用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字符串。

如果您确实要避免重复页面内容,那么您也可以调用现有的toHtmlWithValue,其中包含您控制的特殊分隔符,例如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的精美印刷可能没有得到很好的优化。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...