purescript-argonaut: декодировать произвольное значение ключа json - PullRequest
0 голосов
/ 11 июня 2019

Есть ли способ декодировать произвольный json (например: мы не знаем ключей во время компиляции)?

Например, мне нужно проанализировать следующий json:

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

где имена и количество ключей не известны во время компиляции и могут меняться в зависимости от запроса GET.Цель в основном состоит в том, чтобы декодировать это в Map String (Array String) тип

Есть ли способ сделать это, используя purescript-argonaut?

Ответы [ 2 ]

1 голос
/ 11 июня 2019

Экземпляр Map из EncodeJSON сгенерирует массив кортежей, вы можете вручную построить карту и увидеть закодированный 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
0 голосов
/ 11 июня 2019

Вы можете полностью написать свое собственное, сначала проанализировав строку в Json через jsonParser, а затем изучив получившуюся структуру данных с помощью различных предоставленных комбинаторов. Аргонавт .

Но самый быстрый и простой способ, я думаю, состоит в том, чтобы сначала разобрать его в 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 _)
...