简体   繁体   English

Elm中的解码字典由于额外的反斜杠而失败

[英]Decoding Dict in Elm failing due to extra backslashes

I'm trying to send a dict to javascript via port for storing the value in localStorage, and retrieve it next time the Elm app starts via flag . 我正在尝试通过portdict发送到javascript以将值存储在localStorage中,并在下次Elm应用通过flag启动时检索它。

Below code snippets show the dict sent as well as the raw json value received through flag . 下面的代码片段显示了已发送的dict以及通过flag接收的原始json值。 The Json decoding fails showing the error message at the bottom. Json解码失败,在底部显示错误消息。

The issue seems to be the extra backslashes (as in \\"{\\\\"Left\\\\") contained in the raw flag value. Interestingly, console.log shows that the flag value passed by javascript is "dict1:{"Left":"fullHeightVerticalCenter","Right":"fullHeightVerticalCenter","_default":"fullHeightVerticalBottom"}" as intended, so the extra backslashes seem to be added by Elm, but I can't figure out why. Also, I'd be interested to find out a better way to achieve passing a dict to and from javascript. 问题似乎是原始标志值中包含多余的反斜杠(如\\“ {\\\\” Left \\\\“)。有趣的是, console.log显示javascript传递的flag值为"dict1:{"Left":"fullHeightVerticalCenter","Right":"fullHeightVerticalCenter","_default":"fullHeightVerticalBottom"}"按预期使用,因此Elm似乎添加了额外的反斜杠,但我不知道为什么。有兴趣找到一种更好的方法来实现将dict与javascript相互传递。

import Json.Decode as JD
import Json.Encode as JE

dict1 = Dict.fromList[("_default", "fullHeightVerticalBottom")
                        , ("Left", "fullHeightVerticalCenter")
                        , ("Right", "fullHeightVerticalCenter")]

type alias FlagsJEValue =
   {dict1: String}

port setStorage : FlagsJEValue -> Cmd msg

-- inside Update function Cmd
setStorage {dict1 = JE.encode 0 (dictEncoder JE.string model.dict1)}

dictEncoder enc dict = 
   Dict.toList dict 
     |> List.map (\(k,v) -> (k, enc v)) 
     |> JE.object 
-- 
type alias Flags =
   {dict1: Dict String String} 

flagsDecoder : Decoder Flags
flagsDecoder =
    JD.succeed Flags
     |> required "dict1" (JD.dict JD.string)

-- inside `init`
case JD.decodeValue MyDecoders.flagsDecoder raw_flags of
   Err e ->
      _ = Debug.log "raw flag value" (Debug.toString (JE.encode 2 raw_flags) )
      _ = Debug.log "flags error msg" (Debug.toString e)

      ... omitted ...

   Ok flags ->
      ... omitted ...


-- raw flag value
"{\n  \"dict1\": \"{\\\"Left\\\":\\\"fullHeightVerticalCenter\\\",\\\"Right\\\":\\\"fullHeightVerticalCenter\\\",\\\"_default\\\":\\\"fullHeightVerticalBottom\\\"}\"\n}"

 --flags error msg

"Failure \"Json.Decode.oneOf failed in the following 2 ways:\\n\\n\\n\\n
(1) Problem with the given value:\\n    \\n    \\\"{\\\\\\\"Left\\\\\\\":\\\\\\\"fullHeightVerticalCenter\\\\\\\",\\\\\\\"Right\\\\\\\":\\\\\\\"fullHeightVerticalCenter\\\\\\\",\\\\\\\"_default\\\\\\\":\\\\\\\"fullHeightVerticalBottom\\\\\\\"}\\\"\\n    \\n    Expecting an OBJECT\\n\\n\\n\\n

(2) Problem with the given value:\\n    \\n    \\\"{\\\\\\\"Left\\\\\\\":\\\\\\\"fullHeightVerticalCenter\\\\\\\",\\\\\\\"Right\\\\\\\":\\\\\\\"fullHeightVerticalCenter\\\\\\\",\\\\\\\"_default\\\\\\\":\\\\\\\"fullHeightVerticalBottom\\\\\\\"}\\\"\\n    \\n    Expecting null\" <internals>”

You don't need to use JE.encode there. 您不需要在那里使用JE.encode

You can just use your dictEncoder to produce a Json.Encode.Value and pass that directly to setStorage . 您可以只使用dictEncoder生成Json.Encode.Value并将其直接传递给setStorage

The problem you're encountering it that you've encoded the dict to a json string (using JE.encode ) and then sent that string over a port and the port has encoded that string as json again. 您遇到的问题是,已将dict编码为json字符串(使用JE.encode ),然后通过端口发送该字符串,并且端口再次将该字符串编码为json。 You see extra slashes because the json string is double encoded. 您会看到额外的斜杠,因为json字符串是双重编码的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM