View Javadoc

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