View Javadoc

1   /*
2    * $Id: JsonData.java 20383 2010-11-29 19:44:13Z dfeist $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.module.json;
12  
13  import org.codehaus.jackson.JsonNode;
14  import org.codehaus.jackson.map.ObjectMapper;
15  
16  import java.io.IOException;
17  import java.io.InputStream;
18  import java.io.Reader;
19  import java.io.Serializable;
20  import java.io.StringReader;
21  import java.net.URL;
22  import java.util.ArrayList;
23  import java.util.List;
24  
25  /**
26   * A wrapper for the {@link org.codehaus.jackson.JsonNode} object that
27   * allows for nested object keys i.e. user/name will return the name property on
28   * the user object.
29   * <p/>
30   * There is no 'xpath' for JSON yet (though I expect Jackson to do implement this at some point).  
31   * This class provides a simple way to navigate a Json data structure. To select a child entry use -
32   * <code>
33   * person/name
34   * </code>
35   * <p/>
36   * to access array data, use square braces with an index value i.e.
37   * <code>
38   * person/addresses[0]/postcode
39   * <p/>
40   * or
41   * <p/>
42   * [0]/arrayElement
43   * </code>
44   * <p/>
45   * Also, multi-dimensional arrays can be accessed using:
46   * <code>
47   * filters[1]/init[1][0]
48   * </code>
49   * <p/>
50   * if a Json property name contains a '/' the name needs to be quoted with single quotes i.e.
51   * <p/>
52   * <code>
53   * results/'http://foo.com'/value
54   * </code>
55   */
56  public class JsonData implements Serializable
57  {
58      private JsonNode node;
59  
60      public JsonData(JsonNode node)
61      {
62          this.node = node;
63      }
64  
65      public JsonData(URL node) throws IOException
66      {
67          this(node.openStream());
68      }
69  
70      public JsonData(InputStream node) throws IOException
71      {
72          this.node = new ObjectMapper().readTree(node);
73      }
74  
75      public JsonData(Reader node) throws IOException
76      {
77          this.node = new ObjectMapper().readTree(node);
78      }
79  
80      public JsonData(String node) throws IOException
81      {
82          this(new StringReader(node));
83      }
84  
85      public JsonNode get(int index)
86      {
87          return node.get(index);
88      }
89  
90      public boolean isArray()
91      {
92          return node.isArray();
93      }
94  
95      public JsonNode get(String expression)
96      {
97          List<String> tokens = parseTokens(expression);
98  
99          JsonNode o = node;
100         for (String token : tokens)
101         {
102             if (token.startsWith("["))
103             {
104                 if (o.isArray())
105                 {
106                     int index = Integer.valueOf(token.substring(1, token.length() - 1));
107                     o = o.path(index);
108                 }
109                 else
110                 {
111                     throw new IllegalArgumentException("Current node is not an array, but expression is expecting one");
112                 }
113             }
114             else
115             {
116                 o = o.path(token);
117             }
118 
119             if (o.isMissingNode())
120             {
121                 throw new IllegalArgumentException("Not a valid element: " + token);
122             }
123         }
124 
125         return o;
126     }
127     
128     public String getAsString(String expression)
129     {
130         JsonNode node = get(expression);
131         if (node.isValueNode())
132         {
133             return node.getValueAsText();
134         }
135         else
136         {
137             return node.toString();
138         }
139     }
140     
141     public boolean hasNode(String key)
142     {
143         JsonNode result = node.path(key);
144         return result.isMissingNode() == false;
145     }
146 
147     protected List<String> parseTokens(String expresion)
148     {
149         List<String> tokens = new ArrayList<String>();
150         while (expresion.length() > 0)
151         {
152             int slash = expresion.indexOf("/");
153             int brace = expresion.indexOf("[");
154             //Handled quoted strings
155             if (expresion.charAt(0) == '\'')
156             {
157                 if (expresion.endsWith("'"))
158                 {
159                     tokens.add(expresion.substring(1, expresion.length() - 1));
160                     expresion = "";
161                 }
162                 else
163                 {
164                     int x = expresion.indexOf("'/");
165                     tokens.add(expresion.substring(1, x));
166                     expresion = expresion.substring(x + 2);
167                 }
168             }
169             else if (slash == -1 && brace == -1)
170             {
171                 tokens.add(expresion);
172                 expresion = "";
173             }
174             else if ((slash > -1 && slash < brace) || brace == -1)
175             {
176                 if (slash == 0)
177                 {
178                     if (expresion.charAt(1) == '\'')
179                     {
180                         int x = expresion.indexOf("'", 2);
181                         tokens.add(expresion.substring(2, x));
182                         expresion = expresion.substring(x + 1);
183                     }
184                     else if (expresion.charAt(1) == '[')
185                     {
186                         int i = expresion.indexOf("]", 1);
187                         tokens.add(expresion.substring(0, i));
188                         expresion = expresion.substring(i + 1);
189                     }
190                     else
191                     {
192                         expresion = expresion.substring(slash + 1);
193                     }
194                 }
195                 else
196                 {
197                     tokens.add(expresion.substring(0, slash));
198                     expresion = expresion.substring(slash + 1);
199                 }
200             }
201             else if (brace > 0)
202             {
203                 tokens.add(expresion.substring(0, brace));
204                 expresion = expresion.substring(brace);
205 
206             }
207             else
208             {
209                 int i = expresion.indexOf("]", brace);
210                 tokens.add(expresion.substring(0, i + 1));
211                 expresion = expresion.substring(i + 1);
212             }
213         }
214         return tokens;
215     }
216 
217     @Override
218     public boolean equals(Object obj)
219     {
220         return node.equals(obj);
221     }
222     
223     @Override
224     public int hashCode()
225     {
226         return node.hashCode();
227     }
228 
229     @Override
230     public String toString()
231     {
232         return node.toString();
233     }
234 }