如何使用单个“键值”从JSON对象中提取单个值?

如何使用单个“键值”从JSON对象中提取单个值?,json,haskell,Json,Haskell,Http服务器以以下JSON格式返回数据: { some_value: "fdsafsafdsafs" } 具有单个键和值的对象 我想以这种格式解析返回的数据,但我还不能。我不想为此创建特殊的数据。 相反,我希望解析或解构/模式匹配它,并获得某个_值的值 代码: 二, 三, 所有的尝试都是错误的 如何执行此操作?很可能在第三次尝试时,您没有从中使用Data.HashMap.Strict模块的查找。此外,还应启用重载字符串选项以使用具有文本类型的字符串文字。因此,您可以将其实现为: {-

Http服务器以以下JSON格式返回数据:

{
    some_value: "fdsafsafdsafs"
}
具有单个键和值的对象

我想以这种格式解析返回的数据,但我还不能。我不想为此创建特殊的数据。 相反,我希望解析或解构/模式匹配它,并获得某个_值的值

代码:

二,

三,

所有的尝试都是错误的


如何执行此操作?

很可能在第三次尝试时,您没有从中使用Data.HashMap.Strict模块的查找。此外,还应启用重载字符串选项以使用具有文本类型的字符串文字。因此,您可以将其实现为:

{-# LANGUAGE OverloadedStrings #-}

import qualified Data.HashMap.Strict as HM
import qualified Data.ByteString as BS
import qualified Data.Text as T
import qualified Data.Aeson as Aeson


func1 :: IO (Either MyError BS.ByteString)
func1 = do
  resp <- sendRequestAndReturnJsonBody
  case Aeson.decode resp of
      Just (Aeson.Object obj) -> case (HM.lookup "some_value" obj) of
          Just (Aeson.String s) -> pure (Right s)
          _ -> undefined
      _ -> undefined
它有一个类型,即给定resp是一个ByteString,它将返回一个Applicative f=>f或一个Text,因此如果在您的情况下resp确实是一个值,它可以返回一个IO或MyError

对于包含一个元素的对象,我们可以使用扩展名,从而利用该扩展名在该HashMap的列表模式上进行模式匹配:


对于更多项目,这将不匹配。尝试对更多项执行此操作可能会失败,因为带有toList的项的顺序未指定,因此可能取决于实现细节。

即使您说不想创建自定义数据类型,这仍然是获取所需的let some_pattern=结果语法的最直接方法。请注意,除了解析之外,不需要将数据类型用于任何其他用途。可以将其视为创建新图案的常用Aeson方法,您可以在其上匹配结果

您可以使用泛型定义数据类型,也可以编写自定义FromJSON实例,以避免名称空间中的某个值字段混乱:


是否可以执行类似于此的操作,让对象具有一些值,字符串s=resp。我试过了,但没有compile@Rubashka351:这会很奇怪,因为一个对象正在包装一个HashMap。对于单例对象,可以使用重载列表扩展。
case Aeson.decode resp of
  Just (Aeson.Object obj) -> -- how to exctract "some_value" from "obj" now?
  _ -> _
let (Aeson.Object ("some_value", String s)) = resp
-- [......]
case resp of
  (Object obj) -> 
    case (lookup "some_value" obj) of
      Just (String s) -> pure $ Right s
      _ -> undefined
{-# LANGUAGE OverloadedStrings #-}

import qualified Data.HashMap.Strict as HM
import qualified Data.ByteString as BS
import qualified Data.Text as T
import qualified Data.Aeson as Aeson


func1 :: IO (Either MyError BS.ByteString)
func1 = do
  resp <- sendRequestAndReturnJsonBody
  case Aeson.decode resp of
      Just (Aeson.Object obj) -> case (HM.lookup "some_value" obj) of
          Just (Aeson.String s) -> pure (Right s)
          _ -> undefined
      _ -> undefined
f :: Applicative f => ByteString -> f (Either a Text)
f resp = case Aeson.decode resp of
      Just (Aeson.Object obj) -> case (HM.lookup "some_value" obj) of
          Just (Aeson.String s) -> pure (Right s)
          _ -> undefined
      _ -> undefined
{-# LANGUAGE OverloadedLists, OverloadedStrings #-}

import qualified Data.ByteString as BS
import qualified Data.Text as T
import qualified Data.Aeson as Aeson


func1 :: IO (Either MyError BS.ByteString)
func1 = do
  resp <- sendRequestAndReturnJsonBody
  case Aeson.decode resp of
      Just (Aeson.Object [("some_value", Aeson.String s)]) -> pure (Right s)
      _ -> undefined
{-# LANGUAGE OverloadedStrings #-}

import Data.ByteString (ByteString)
import Data.Aeson

newtype SomeValue = SomeValue String
instance FromJSON SomeValue where
  parseJSON = withObject "SomeValue" $ \o -> SomeValue <$> o .: "some_value"

myjson :: ByteString
myjson = "{ \"some_value\": \"fdsafsafdsafs\" }"

main = do
  case decodeStrict myjson of
    Just (SomeValue v) -> print v
    _ -> error "didn't work!"