如何在Elm中操作Json.Encode.Value?

时间:2018-06-22 15:05:52

标签: json elm

我正在为Elm数据结构编写一些代码以自动生成JSON编解码器。有一点我的代码已经将“子结构/子类型”编码为Json.Encode.Value,并且我需要向其添加另一个键值对。有什么方法可以在榆木中“分解” Json.Encode.Value?还是合并两个Json.Encode.Value类型的值?

下面是一些示例代码:

type alias Entity record =
   { entityKey: (Key record)
   , entityVal: record
   }

jsonEncEntity : (record -> Value) -> Entity record -> Value
jsonEncEntity localEncoder_record val =
  let 
      encodedRecord = localEncoder_record val.entityVal
  in
      -- NOTE: the following line won't compile, but this is essentially
      -- what I'm looking for
      Json.combine encodedRecord (Json.Encode.object [ ( "id", jsonEncKey val.entityKey ) ] )

2 个答案:

答案 0 :(得分:2)

您可以使用D.keyValuePairs D.value将值解码为键值对列表,然后附加新字段。这是您的处理方式:

module Main exposing (..)

import Json.Decode as D
import Json.Encode as E exposing (Value)


addKeyValue : String -> Value -> Value -> Value
addKeyValue key value input =
    case D.decodeValue (D.keyValuePairs D.value) input of
        Ok ok ->
            E.object <| ( key, value ) :: ok

        Err _ ->
            input
> import Main
> import Json.Encode as E
> value = E.object [("a", E.int 1)]
{ a = 1 } : Json.Encode.Value
> value2 = Main.addKeyValue "b" E.null value
{ b = null, a = 1 } : Json.Encode.Value

如果输入不是对象,则输入将保持不变:

> Main.addKeyValue "b" E.null (E.int 1)
1 : Json.Encode.Value

答案 1 :(得分:1)

如果要执行此操作,则需要使用解码器将这些值按一级解包到Dict String Value中,然后组合字典,最后将其重新编码为JSON值。您可以这样展开:

unwrapObject : Value -> Result String (Dict String Value)
unwrapObject value =
    Json.Decode.decodeValue (Json.Decode.dict Json.Decode.value) value

请注意,从现在开始,您必须使用Result,因为就Elm而言,您的JSON值实际上不是对象(可能是数字或例如字符串),您必须处理这种情况。因此,直接对JSON Value进行过多处理并不是真正的最佳实践;如果可以的话,将其保留为Dict或其他更多信息类型,直到处理结束,然后将整个结果转换为Value作为最后一步。