Haskell JSON data processing

Source: Internet
Author: User
Tags ord

The basic types of JSON are--string, numbers, booleans, and NULL, which define the JSON type as follows

--FILE:JSON.HS
Module Json where
Data Jvalue = jstring String
           |  Jnumber Double
           |  Jbool Bool
           |  
           |  Jobject [(String, Jvalue)]
           |  Jarray [Jvalue]
              Deriving (Eq, Ord, Show)

Print JSON type data

--FILE:PUTJSON.HS
Module Putjson where
Import Data.list (intercalate)
Import Json
Renderjvalue:: jvalue–> String
Renderjvalue (jstring s) = Show S
Renderjvalue (jnumber N) = Show n
Renderjvalue (jbool true) = "true"
Renderjvalue (Jbool false) = "false"
Renderjvalue jnull         = "NULL"
Renderjvalue (jobject o) = "{" + + pairs O + + "}"
    where pairs [] = ""
          Pairs PS = intercalate "," (Map Renderpair PS)
          Renderpair (k, v) = Show K + + ":" + + Renderjvalue V
Renderjvalue (Jarray a) = "[" + + values A + + "]"
    where values [] = ""
          Values vs = Intercalate "," (Map Renderjvalue vs)
Putjvalue:: jvalue–> IO ()
Putjvalue v = putstrln (Renderjvalue v)

Finally write the call file

--FILE:MAIN.HS
Module Main where
Main = Putjvalue (Jobject [("foo", Jnumber 1), ("Bar", Jbool False)])

Enter the following instruction on the command line

Ghc–o Demo Json.hs putjson.hs main.hs

Generate Demo.exe, and then enter demo on the command line to get the Jvalue print string. If the value structure of the jvalue is very complex, it is not friendly to humans to print it out in this way. Well, how about a friendly print out?

Assuming we have a module prettify, the API of this module converts jvalue to Doc instead of the above string, we rewrite the render function as follows,

--FILE:PRETTYJSON.HS
Renderjvalue:: jvalue–> Doc
Renderjvalue (Jbool true)  = text "true"
Renderjvalue (Jbool false) = text "false"
Renderjvalue jnull         = text "null"
Renderjvalue (jnumber num) = Double num
Renderjvalue (jstring str) = string str

Among them, the doc type, text,double and string functions are implemented by our Prettify module.

Give the definition of the string function first

--FILE:PRETTYJSON.HS
String:: String–> Doc
String = Enclose ' "'". Hcat. Map Onechar

This definition uses the free-point style (free-point style), the original function is left-to-right operation, the use of free-point style, after the equivalent of

--FILE:PRETTYJSON.HS
String:: String–> Doc
string s = Enclose ' "" ' (Hcat (map Onechar s))                                          (1)

As you can see, using this style, omit the parameter s and replace the parentheses with the dot number. In this definition, there are various functions that are now broken down in turn. The enclose function appends characters to the front and back of a Doc object, as defined below

--FILE:PRETTYJSON.HS
Enclose:: char–> char–> doc–> Doc
Enclose left Right x = char left <> x <> char Right

Char is a function that converts a char character type to a doc type, and we do not yet know its method body by first using undefined to represent its method body, so that the signature is as follows.

--FILE:PRETTYJSON.HS
Char:: char–> Doc
char c = undefined

<> is an infix function, written in the middle of two operational components, as an operator, its operation priority ratio as a function of the char bottom, so the enclose function method body can see, The Char function converts the char character type parameter left and right to two doc type parameters, and then joins with the other doc type parameter X with two <> operators, easy to know that the,<> connects two doc type parameters, and gets another doc type result, The signature is as follows, in fact, this <> operator is similar to the (+ +) operator of string type, which is to concatenate two doc parameters and generate a new doc type result.

--FILE:PRETTYJSON.HS
(<>):: doc–> doc–> Doc
a <> b = undefined

We look at (1) and now we know that the function of the string function is to add double quotation marks (") to both sides of the Doc type value (Hcat (map Onechar s)), and then we look at the Hcat function, which is similar to the list's join function concat (Note < The difference between >), signed as follows

--FILE:PRETTYJSON.HS
Hcat:: [doc]-> Doc
Hcat xs = undefined

Next, since the map function applies the Onechar function to each element of the list s, we just have to look at what the Onechar function is for. Since S is a string type, the Onechar function converts a char type to a doc type, giving a detailed definition of the function as follows.

--FILE:PRETTYJSON.HS
Onechar:: char–> Doc
              Just r–> Text R
              Nothing | Mustescape–> Hexescape C
                      | Otherwise  ,  char C
    where Mustescape C = C < ' | | c = = ' \x7f ' | | C > ' \xff '
Simpleescapes:: [(Char, String)]
simpleescapes = Zipwith ch "\b\n\f\r\t\\\"/"bnfrt\\\"/"
    where ch a b = (a, [' \ \ \ ', b]

This function definition is a little bit large, we see at 1.1, first simpleescapes is a list of two tuples, the first element of the tuple is a simple escape character (\b, \ n, \f, \ r, \ t, \ \, \ ",/), the second is to show the first item, such as ' \b ', Performance as "\\b", you can write a test as follows

Prelude>: Load PRETTYJSON.HS
Prelude> Take 8 simpleescapes
[(' \b ', "\\b"), (' \ n ', "\\n"), (' \f ', "\\f"), (' \ R ', "\\r"), (' \ t ', "\\t"), (' \ \ ', "\\\\"), (' "'," \\\ "), ('/'," \\/")]

The lookup function checks whether the character C is the first item in a tuple in Simpleescapes, returns the string representation of the escaped character, and if the character C is not a simple escape character, if it is another character that needs to be escaped, apply the Hexescape function to character C. Otherwise, it is a simple character that does not need to be escaped, and the char function is applied directly to the doc type.

There is also a function hexescape has not given the parsing. We give a direct definition as follows

--FILE:PRETTYJSON.HS
Hexescape:: char–> Doc
Hexescape C | D < 0x10000 = Smallhex D
            | otherwise   = Astral (d–0x10000)
    where d = Ord C

Depending on whether the ASCII value of character C is less than 0x10000, the code value of character C is processed differently.

--FILE:PRETTYJSON.HS
Smallhex:: int–> Doc
Smallhex x = text "\\u"
          <> text (Replicate (4–length h) ' 0 ')
          <> text H
    where h = Showhex x ""

Where the Showhex function comes from the numeric library, you need to import the library at the beginning of the file. The function of the Showhex function is to print a number in 16 binary. The replicate function is to repeat a specified type a n times to generate a list of type a

Replicate:: Int–> a–> [A]

According to the definition of Hexescape, the ASCII value of character C (16 binary) is not more than 4 bits long (according to the guard expression is d< 0x10000), so the range of 4–length H is [0, 4],smallhex function is to print the parameter x, Print "\\u" first, then the number of 16 digits of X if it is less than 4 bits, 0 makes up 4 bits, then prints the 16 binary value of X.

The Smallhex function can print a value of up to 0xFFFF, while the valid Unicode character range is up to 0x10ffff, to the character of (0xFFFF, 0X10FFFF), and the Astral function is applied, and its definition is given as follows

--FILE:PRETTYJSON.HS
Astral:: Int–> Doc
Astral n = smallhex (A + 0xd800) <> Smallhex (b + 0xdc00)
    where a = (n ' shiftr '). &. 0x3ff
          b = N. &. 0x3ff

Where Shiftr is the right-shift function, (. &.) is bitwise-With. Let's take a look at how the Astral function handles parameter n, for parameter n, takes its low 10 bits as B, takes its 11th to 20th bit (lower 10 bits) as a, of course, the previous argument range is (0xFFFF, 0X10FFFF), the value of the number of bits is 17 to 20 bits, so a Is high 10 bits, B is low 10 bits.

Haskell JSON data processing

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.