简体   繁体   English

purescript-argonaut:解码任意键值json

[英]purescript-argonaut: Decode arbitrary key-value json

Is there a way to decode arbitrary json (eg: We don't know the keys at compile time)? 有没有一种方法可以解码任意的json(例如:我们在编译时不知道键)?

For example, I need to parse the following json: 例如,我需要解析以下json:

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

where the names and number of keys are not known at compile time and may change per GET request. 其中键的名称和数量在编译时未知,并且可能会因GET请求而更改。 The goal is basically to decode this into a Map String (Array String) type 目标基本上是将其解码为Map String (Array String)类型

Is there a way to do this using purescript-argonaut? 有没有一种方法可以使用purescript-argonaut?

The Map instance of EncodeJSON will generate an array of tuple, you can manually construct a Map and see the encoded json. EncodeJSONMap实例将生成一个元组数组,您可以手动构造Map并查看编码的json。

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

Output should be [ [ 'Foo', [ 'Value1', 'Value2' ] ] ] . 输出应为[ [ 'Foo', [ 'Value1', 'Value2' ] ] ]

To do the reverse, you need to transform you object to an array of tuple, Object.entries can help you. 为此,您需要将对象转换为元组数组, Object.entries可以为您提供帮助。

An example 一个例子

// 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

You can totally write your own by first parsing the string into Json via jsonParser , and then examining the resulting data structure with the various combinators provided by Argonaut . 您可以完全自己编写自己的代码,方法是先通过jsonParser将字符串解析为Json ,然后使用Argonaut提供各种组合器检查结果数据结构。

But the quickest and simplest way, I think, is to parse it into Foreign.Object (Array String) first, and then convert to whatever your need, like Map String (Array String) : 但是,我认为最快,最简单的方法是Foreign.Object (Array String)其解析为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 _)

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

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