-- | Efficient generation of JSON documents.{-# LANGUAGE GeneralizedNewtypeDeriving #-}{-# LANGUAGE CPP #-}{-# LANGUAGE OverloadedStrings #-}moduleYesod.Json(-- * MonadJson,jsonToContent,jsonToRepJson-- * Generate Json output,jsonScalar,jsonList,jsonMap,jsonRaw#if TEST,testSuite#endif)whereimportqualifiedData.ByteString.Char8asSimportData.Char(isControl)importYesod.Handler(GHandler)importNumeric(showHex)importData.Monoid(Monoid(..))importText.Blaze.Builder.CoreimportText.Blaze.Builder.Utf8(writeChar)#if TESTimportTest.Framework(testGroup,Test)importTest.Framework.Providers.HUnitimportTest.HUnithiding(Test)importData.ByteString.Lazy.Char8(unpack)importYesod.Contenthiding(testSuite)#elseimportYesod.Content#endif-- | A monad for generating Json output. It wraps the Builder monoid from the-- blaze-builder package.---- This is an opaque type to avoid any possible insertion of non-JSON content.-- Due to the limited nature of the JSON format, you can create any valid JSON-- document you wish using only 'jsonScalar', 'jsonList' and 'jsonMap'.newtypeJson=Json{unJson::Builder}derivingMonoid-- | Extract the final result from the given 'Json' value.---- See also: applyLayoutJson in "Yesod.Yesod".jsonToContent::Json->GHandlersubmasterContentjsonToContent=return.toContent.toLazyByteString.unJson-- | Wraps the 'Content' generated by 'jsonToContent' in a 'RepJson'.jsonToRepJson::Json->GHandlersubmasterRepJsonjsonToRepJson=fmapRepJson.jsonToContent-- | Outputs a single scalar. This function essentially:---- * Performs JSON encoding.---- * Wraps the resulting string in quotes.jsonScalar::String->JsonjsonScalars=Json$mconcat[fromByteString"\"",writeListwriteJsonChars,fromByteString"\""]wherewriteJsonChar'\b'=writeByteString"\\b"writeJsonChar'\f'=writeByteString"\\f"writeJsonChar'\n'=writeByteString"\\n"writeJsonChar'\r'=writeByteString"\\r"writeJsonChar'\t'=writeByteString"\\t"writeJsonChar'"'=writeByteString"\\\""writeJsonChar'\\'=writeByteString"\\\\"writeJsonCharc|not$isControlc=writeCharc|c<'\x10'=writeString$'\\':'u':'0':'0':'0':hexxs|c<'\x100'=writeString$'\\':'u':'0':'0':hexxs|c<'\x1000'=writeString$'\\':'u':'0':hexxswherehexxs=showHex(fromEnumc)""writeJsonCharc=writeCharcwriteString=writeByteString.S.pack-- | Outputs a JSON list, eg [\"foo\",\"bar\",\"baz\"].jsonList::[Json]->JsonjsonList[]=Json$fromByteString"[]"jsonList(x:xs)=mconcat[Json$fromByteString"[",x,mconcat$mapgoxs,Json$fromByteString"]"]wherego=mappend(Json$fromByteString",")-- | Outputs a JSON map, eg {\"foo\":\"bar\",\"baz\":\"bin\"}.jsonMap::[(String,Json)]->JsonjsonMap[]=Json$fromByteString"{}"jsonMap(x:xs)=mconcat[Json$fromByteString"{",gox,mconcat$mapgo'xs,Json$fromByteString"}"]wherego'y=mappend(Json$fromByteString",")$goygo(k,v)=mconcat[jsonScalark,Json$fromByteString":",v]-- | Outputs raw JSON data without performing any escaping. Use with caution:-- this is the only function in this module that allows you to create broken-- JSON documents.jsonRaw::S.ByteString->JsonjsonRaw=Json.fromByteString#if TESTtestSuite::TesttestSuite=testGroup"Yesod.Json"[testCase"simple output"caseSimpleOutput]caseSimpleOutput::AssertioncaseSimpleOutput=doletj=dojsonMap[("foo",jsonList[jsonScalar"bar",jsonScalar"baz"])]"{\"foo\":[\"bar\",\"baz\"]}"@=?unpack(toLazyByteString$unJsonj)#endif