purescript-argonaut:解码任意键值 json

purescript-argonaut: Decode arbitrary key-value json

有没有办法解码任意 json(例如:我们在编译时不知道密钥)?

比如我需要解析如下json:

{ 
    "Foo": [
        "Value 1",
        "Value 2"
    ],
    "Bar": [
        "Bar Value 1"
    ],
    "Baz": []
}

其中键的名称和数量在编译时未知,并且可能会根据 GET 请求更改。目标基本上是将其解码为 Map String (Array String) 类型

有没有办法使用 purescript-argonaut 做到这一点?

EncodeJSONMap实例会生成一个元组数组,可以手动构造一个Map,看编码后的json。

let v = Map.fromFoldable [ Tuple "Foo" ["Value1", "Value2"] ]
traceM $ encodeJson v

输出应该是 [ [ 'Foo', [ 'Value1', 'Value2' ] ] ].

要进行相反的操作,您需要将对象转换为元组数组,Object.entries 可以帮助您。

一个例子

// Main.js
var obj = {
  foo: ["a", "b"],
  bar: ["c", "d"]
};

exports.tuples = Object.entries(obj);

exports.jsonString = JSON.stringify(exports.tuples);
-- Main.purs
module Main where

import Prelude

import Data.Argonaut.Core (Json)
import Data.Argonaut.Decode (decodeJson)
import Data.Argonaut.Parser (jsonParser)
import Data.Either (Either)
import Data.Map (Map)
import Debug.Trace (traceM)
import Effect (Effect)
import Effect.Console (log)

foreign import tuples :: Json
foreign import jsonString :: String

main :: Effect Unit
main = do
  let
    a = (decodeJson tuples) :: Either String (Map String (Array String))
    b = (decodeJson =<< jsonParser jsonString) :: Either String (Map String (Array String))
  traceM a
  traceM b
  traceM $ a == b

您完全可以自己编写,方法是先将字符串解析为 Json via jsonParser, and then examining the resulting data structure with the various combinators provided by Argonaut

但我认为最快最简单的方法是先将其解析为Foreign.Object (Array String),然后再转换为您需要的任何内容,例如Map String (Array String):

import Data.Argonaut (decodeJson, jsonParser)
import Data.Either (Either)
import Data.Map as Map
import Foreign.Object as F

decodeAsMap :: String -> Either _ (Map.Map String (Array String))
decodeAsMap str = do
    json <- jsonParser str
    obj <- decodeJson json
    pure $ Map.fromFoldable $ (F.toUnfoldable obj :: Array _)