You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Haskell将数据编码为JSON?Haskell新手求助

从Python到Haskell:轻松搞定JSON编码

嘿,作为Haskell新手,刚碰Aeson的时候我也觉得文档太抽象了——完全摸不着头脑!别担心,咱们从最实用的例子入手,一步步来,你很快就能输出JSON了。

第一步:准备好依赖

首先得确保你的项目里包含了aeson库。如果用Cabal,在你的.cabal文件里加一行:

build-depends: base >=4.14 && <5, aeson

如果用Stack,就在package.yaml的dependencies里加上aeson。

第二步:基础类型的JSON编码

先从简单的开始——Haskell的基础类型(字符串、数字、列表、布尔值)都已经默认实现了ToJSON接口,直接用encode函数就行。注意encode返回的是ByteString.Lazy类型,得转成普通字符串才能输出:

import Data.Aeson (encode)
import Data.ByteString.Lazy.Char8 (unpack)  -- 用来把ByteString转成String

main :: IO ()
main = do
  -- 编码字符串
  putStrLn $ unpack $ encode "Hello Haskell JSON!"
  -- 输出:"\"Hello Haskell JSON!\""

  -- 编码整数
  putStrLn $ unpack $ encode 42
  -- 输出:"42"

  -- 编码布尔值
  putStrLn $ unpack $ encode True
  -- 输出:"true"

  -- 编码列表
  putStrLn $ unpack $ encode [1, 3, 5]
  -- 输出:"[1,3,5]"

第三步:自定义数据类型的编码

这才是你大概率会用到的场景——把自己定义的数据结构转成JSON。这里有两种方式:自动推导(省力)和手动实现(灵活)。

方式1:自动推导实例(推荐新手)

只要启用DeriveGeneric扩展,让你的数据类型派生Generic,就能自动生成ToJSON实例,不用自己写任何转换逻辑:

{-# LANGUAGE DeriveGeneric #-}  -- 顶部启用扩展

import Data.Aeson (ToJSON, encode)
import Data.ByteString.Lazy.Char8 (unpack)
import GHC.Generics (Generic)  -- 导入Generic类型

-- 定义你的数据类型
data User = User
  { username :: String
  , email    :: String
  , age      :: Int
  , isActive :: Bool
  } deriving (Generic, Show)  -- 派生Generic和Show

-- 自动生成ToJSON实例
instance ToJSON User

main :: IO ()
main = do
  let me = User "john_doe" "john@example.com" 30 True
  putStrLn $ unpack $ encode me
  -- 输出:{"username":"john_doe","email":"john@example.com","age":30,"isActive":true}

方式2:手动实现实例(定制需求)

如果需要自定义JSON的字段名(比如把Haskell里的驼峰式改成下划线式),或者处理特殊逻辑,就手动写ToJSON实例:

import Data.Aeson (ToJSON(..), object, (.=))  -- 导入object和(.=)
import Data.ByteString.Lazy.Char8 (unpack)

data User = User
  { username :: String
  , email    :: String
  , age      :: Int
  , isActive :: Bool
  } deriving (Show)

-- 手动实现ToJSON
instance ToJSON User where
  toJSON (User uname mail userAge active) = object
    [ "user_name" .= uname  -- 把字段名改成user_name,而不是默认的username
    , "email_address" .= mail
    , "user_age" .= userAge
    , "active_status" .= active
    ]

main :: IO ()
main = do
  let me = User "john_doe" "john@example.com" 30 True
  putStrLn $ unpack $ encode me
  -- 输出:{"user_name":"john_doe","email_address":"john@example.com","user_age":30,"active_status":true}

这里的object函数用来构建JSON对象,(.=)用来创建键值对——很像Python里的字典推导吧?

常见问题排查

你说“无法输出JSON”,大概率是这几个原因:

  • 忘记实现ToJSON实例:如果直接encode自定义类型,编译器会报错——它不知道怎么把你的类型转成JSON,所以必须加instance ToJSON YourType(不管是自动还是手动)。
  • 没处理ByteString:encode返回的是懒加载的ByteString,直接用putStrLn会报错,必须用unpack转成String。
  • 依赖没加对:如果编译时找不到Data.Aeson模块,检查你的Cabal/Stack配置,确保aeson已经在依赖里。

慢慢来,先把基础例子跑通,再尝试复杂的结构——Haskell的JSON处理其实比你想象的更有条理!

内容的提问来源于stack exchange,提问作者Jonathan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 08:40:29