/src/main/java/com/alibaba/fastjson/JSONPath.java

https://github.com/alibaba/fastjson · Java · 1439 lines · 1132 code · 244 blank · 63 comment · 435 complexity · 090fccaaf9e371f8afa6e27e434c7eae MD5 · raw file

  1. package com.alibaba.fastjson;
  2. import com.alibaba.fastjson.parser.DefaultJSONParser;
  3. import com.alibaba.fastjson.parser.Feature;
  4. import com.alibaba.fastjson.parser.JSONLexer;
  5. import com.alibaba.fastjson.parser.JSONLexerBase;
  6. import com.alibaba.fastjson.parser.JSONToken;
  7. import com.alibaba.fastjson.parser.ParserConfig;
  8. import com.alibaba.fastjson.parser.deserializer.FieldDeserializer;
  9. import com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer;
  10. import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer;
  11. import com.alibaba.fastjson.serializer.FieldSerializer;
  12. import com.alibaba.fastjson.serializer.JavaBeanSerializer;
  13. import com.alibaba.fastjson.serializer.ObjectSerializer;
  14. import com.alibaba.fastjson.serializer.SerializeConfig;
  15. import com.alibaba.fastjson.util.IOUtils;
  16. import com.alibaba.fastjson.util.TypeUtils;
  17. import java.lang.reflect.Array;
  18. import java.lang.reflect.InvocationTargetException;
  19. import java.lang.reflect.Type;
  20. import java.math.BigDecimal;
  21. import java.math.BigInteger;
  22. import java.math.RoundingMode;
  23. import java.util.ArrayList;
  24. import java.util.Arrays;
  25. import java.util.Calendar;
  26. import java.util.Collection;
  27. import java.util.Collections;
  28. import java.util.Date;
  29. import java.util.HashMap;
  30. import java.util.IdentityHashMap;
  31. import java.util.Iterator;
  32. import java.util.List;
  33. import java.util.Map;
  34. import java.util.Set;
  35. import java.util.UUID;
  36. import java.util.concurrent.ConcurrentHashMap;
  37. import java.util.concurrent.ConcurrentMap;
  38. import java.util.regex.Matcher;
  39. import java.util.regex.Pattern;
  40. /**
  41. * @author wenshao[szujobs@hotmail.com]
  42. * @since 1.2.0
  43. */
  44. public class JSONPath implements JSONAware {
  45. private static ConcurrentMap<String, JSONPath> pathCache = new ConcurrentHashMap<String, JSONPath>(128, 0.75f, 1);
  46. private final String path;
  47. private Segment[] segments;
  48. private boolean hasRefSegment;
  49. private SerializeConfig serializeConfig;
  50. private ParserConfig parserConfig;
  51. private boolean ignoreNullValue;
  52. public JSONPath(String path){
  53. this(path, SerializeConfig.getGlobalInstance(), ParserConfig.getGlobalInstance(), true);
  54. }
  55. public JSONPath(String path, boolean ignoreNullValue){
  56. this(path, SerializeConfig.getGlobalInstance(), ParserConfig.getGlobalInstance(), ignoreNullValue);
  57. }
  58. public JSONPath(String path, SerializeConfig serializeConfig, ParserConfig parserConfig, boolean ignoreNullValue){
  59. if (path == null || path.length() == 0) {
  60. throw new JSONPathException("json-path can not be null or empty");
  61. }
  62. this.path = path;
  63. this.serializeConfig = serializeConfig;
  64. this.parserConfig = parserConfig;
  65. this.ignoreNullValue = ignoreNullValue;
  66. }
  67. protected void init() {
  68. if (segments != null) {
  69. return;
  70. }
  71. if ("*".equals(path)) {
  72. this.segments = new Segment[] { WildCardSegment.instance };
  73. } else {
  74. JSONPathParser parser = new JSONPathParser(path);
  75. this.segments = parser.explain();
  76. this.hasRefSegment = parser.hasRefSegment;
  77. }
  78. }
  79. public boolean isRef() {
  80. try {
  81. init();
  82. for (int i = 0; i < segments.length; ++i) {
  83. Segment segment = segments[i];
  84. Class segmentType = segment.getClass();
  85. if (segmentType == ArrayAccessSegment.class
  86. || segmentType == PropertySegment.class) {
  87. continue;
  88. }
  89. return false;
  90. }
  91. return true;
  92. } catch (JSONPathException ex) {
  93. // skip
  94. return false;
  95. }
  96. }
  97. public Object eval(Object rootObject) {
  98. if (rootObject == null) {
  99. return null;
  100. }
  101. init();
  102. Object currentObject = rootObject;
  103. for (int i = 0; i < segments.length; ++i) {
  104. Segment segment = segments[i];
  105. currentObject = segment.eval(this, rootObject, currentObject);
  106. }
  107. return currentObject;
  108. }
  109. /**
  110. * @since 1.2.76
  111. * @param rootObject
  112. * @param clazz
  113. * @param parserConfig
  114. * @return
  115. */
  116. public <T> T eval(Object rootObject, Type clazz, ParserConfig parserConfig) {
  117. Object obj = this.eval(rootObject);
  118. return TypeUtils.cast(obj, clazz, parserConfig);
  119. }
  120. /**
  121. * @since 1.2.76
  122. * @param rootObject
  123. * @param clazz
  124. * @return
  125. */
  126. public <T> T eval(Object rootObject, Type clazz) {
  127. return this.eval(rootObject, clazz, ParserConfig.getGlobalInstance());
  128. }
  129. public Object extract(DefaultJSONParser parser) {
  130. if (parser == null) {
  131. return null;
  132. }
  133. init();
  134. if (hasRefSegment) {
  135. Object root = parser.parse();
  136. return this.eval(root);
  137. }
  138. if (segments.length == 0) {
  139. return parser.parse();
  140. }
  141. Segment lastSegment = segments[segments.length - 1];
  142. if (lastSegment instanceof TypeSegment
  143. || lastSegment instanceof FloorSegment
  144. || lastSegment instanceof MultiIndexSegment) {
  145. return eval(
  146. parser.parse());
  147. }
  148. Context context = null;
  149. for (int i = 0; i < segments.length; ++i) {
  150. Segment segment = segments[i];
  151. boolean last = i == segments.length - 1;
  152. if (context != null && context.object != null) {
  153. context.object = segment.eval(this, null, context.object);
  154. continue;
  155. }
  156. boolean eval;
  157. if (!last) {
  158. Segment nextSegment = segments[i + 1];
  159. if (segment instanceof PropertySegment
  160. && ((PropertySegment) segment).deep
  161. && (nextSegment instanceof ArrayAccessSegment
  162. || nextSegment instanceof MultiIndexSegment
  163. || nextSegment instanceof MultiPropertySegment
  164. || nextSegment instanceof SizeSegment
  165. || nextSegment instanceof PropertySegment
  166. || nextSegment instanceof FilterSegment))
  167. {
  168. eval = true;
  169. } else if (nextSegment instanceof ArrayAccessSegment
  170. && ((ArrayAccessSegment) nextSegment).index < 0) {
  171. eval = true;
  172. } else if (nextSegment instanceof FilterSegment) {
  173. eval = true;
  174. } else if (segment instanceof WildCardSegment) {
  175. eval = true;
  176. }else if(segment instanceof MultiIndexSegment){
  177. eval = true;
  178. } else {
  179. eval = false;
  180. }
  181. } else {
  182. eval = true;
  183. }
  184. context = new Context(context, eval);
  185. segment.extract(this, parser, context);
  186. }
  187. return context.object;
  188. }
  189. private static class Context {
  190. final Context parent;
  191. final boolean eval;
  192. Object object;
  193. public Context(Context parent, boolean eval) {
  194. this.parent = parent;
  195. this.eval = eval;
  196. }
  197. }
  198. public boolean contains(Object rootObject) {
  199. if (rootObject == null) {
  200. return false;
  201. }
  202. init();
  203. Object currentObject = rootObject;
  204. for (int i = 0; i < segments.length; ++i) {
  205. Object parentObject = currentObject;
  206. currentObject = segments[i].eval(this, rootObject, currentObject);
  207. if (currentObject == null) {
  208. return false;
  209. }
  210. if (currentObject == Collections.EMPTY_LIST && parentObject instanceof List) {
  211. return ((List) parentObject).contains(currentObject);
  212. }
  213. }
  214. return true;
  215. }
  216. @SuppressWarnings("rawtypes")
  217. public boolean containsValue(Object rootObject, Object value) {
  218. Object currentObject = eval(rootObject);
  219. if (currentObject == value) {
  220. return true;
  221. }
  222. if (currentObject == null) {
  223. return false;
  224. }
  225. if (currentObject instanceof Iterable) {
  226. Iterator it = ((Iterable) currentObject).iterator();
  227. while (it.hasNext()) {
  228. Object item = it.next();
  229. if (eq(item, value)) {
  230. return true;
  231. }
  232. }
  233. return false;
  234. }
  235. return eq(currentObject, value);
  236. }
  237. public int size(Object rootObject) {
  238. if (rootObject == null) {
  239. return -1;
  240. }
  241. init();
  242. Object currentObject = rootObject;
  243. for (int i = 0; i < segments.length; ++i) {
  244. currentObject = segments[i].eval(this, rootObject, currentObject);
  245. }
  246. return evalSize(currentObject);
  247. }
  248. /**
  249. * Extract keySet or field names from rootObject on this JSONPath.
  250. *
  251. * @param rootObject Can be a map or custom object. Array and Collection are not supported.
  252. * @return Set of keys, or <code>null</code> if not supported.
  253. */
  254. public Set<?> keySet(Object rootObject) {
  255. if (rootObject == null) {
  256. return null;
  257. }
  258. init();
  259. Object currentObject = rootObject;
  260. for (int i = 0; i < segments.length; ++i) {
  261. currentObject = segments[i].eval(this, rootObject, currentObject);
  262. }
  263. return evalKeySet(currentObject);
  264. }
  265. public void patchAdd(Object rootObject, Object value, boolean replace) {
  266. if (rootObject == null) {
  267. return;
  268. }
  269. init();
  270. Object currentObject = rootObject;
  271. Object parentObject = null;
  272. for (int i = 0; i < segments.length; ++i) {
  273. parentObject = currentObject;
  274. Segment segment = segments[i];
  275. currentObject = segment.eval(this, rootObject, currentObject);
  276. if (currentObject == null && i != segments.length - 1) {
  277. if (segment instanceof PropertySegment) {
  278. currentObject = new JSONObject();
  279. ((PropertySegment) segment).setValue(this, parentObject, currentObject);
  280. }
  281. }
  282. }
  283. Object result = currentObject;
  284. if ((!replace) && result instanceof Collection) {
  285. Collection collection = (Collection) result;
  286. collection.add(value);
  287. return;
  288. }
  289. Object newResult;
  290. if (result != null && !replace) {
  291. Class<?> resultClass = result.getClass();
  292. if (resultClass.isArray()) {
  293. int length = Array.getLength(result);
  294. Object descArray = Array.newInstance(resultClass.getComponentType(), length + 1);
  295. System.arraycopy(result, 0, descArray, 0, length);
  296. Array.set(descArray, length, value);
  297. newResult = descArray;
  298. }
  299. else if (Map.class.isAssignableFrom(resultClass)) {
  300. newResult = value;
  301. } else {
  302. throw new JSONException("unsupported array put operation. " + resultClass);
  303. }
  304. } else {
  305. newResult = value;
  306. }
  307. Segment lastSegment = segments[segments.length - 1];
  308. if (lastSegment instanceof PropertySegment) {
  309. PropertySegment propertySegment = (PropertySegment) lastSegment;
  310. propertySegment.setValue(this, parentObject, newResult);
  311. return;
  312. }
  313. if (lastSegment instanceof ArrayAccessSegment) {
  314. ((ArrayAccessSegment) lastSegment).setValue(this, parentObject, newResult);
  315. return;
  316. }
  317. throw new UnsupportedOperationException();
  318. }
  319. @SuppressWarnings({ "rawtypes", "unchecked" })
  320. public void arrayAdd(Object rootObject, Object... values) {
  321. if (values == null || values.length == 0) {
  322. return;
  323. }
  324. if (rootObject == null) {
  325. return;
  326. }
  327. init();
  328. Object currentObject = rootObject;
  329. Object parentObject = null;
  330. for (int i = 0; i < segments.length; ++i) {
  331. if (i == segments.length - 1) {
  332. parentObject = currentObject;
  333. }
  334. currentObject = segments[i].eval(this, rootObject, currentObject);
  335. }
  336. Object result = currentObject;
  337. if (result == null) {
  338. throw new JSONPathException("value not found in path " + path);
  339. }
  340. if (result instanceof Collection) {
  341. Collection collection = (Collection) result;
  342. for (Object value : values) {
  343. collection.add(value);
  344. }
  345. return;
  346. }
  347. Class<?> resultClass = result.getClass();
  348. Object newResult;
  349. if (resultClass.isArray()) {
  350. int length = Array.getLength(result);
  351. Object descArray = Array.newInstance(resultClass.getComponentType(), length + values.length);
  352. System.arraycopy(result, 0, descArray, 0, length);
  353. for (int i = 0; i < values.length; ++i) {
  354. Array.set(descArray, length + i, values[i]);
  355. }
  356. newResult = descArray;
  357. } else {
  358. throw new JSONException("unsupported array put operation. " + resultClass);
  359. }
  360. Segment lastSegment = segments[segments.length - 1];
  361. if (lastSegment instanceof PropertySegment) {
  362. PropertySegment propertySegment = (PropertySegment) lastSegment;
  363. propertySegment.setValue(this, parentObject, newResult);
  364. return;
  365. }
  366. if (lastSegment instanceof ArrayAccessSegment) {
  367. ((ArrayAccessSegment) lastSegment).setValue(this, parentObject, newResult);
  368. return;
  369. }
  370. throw new UnsupportedOperationException();
  371. }
  372. public boolean remove(Object rootObject) {
  373. if (rootObject == null) {
  374. return false;
  375. }
  376. init();
  377. Object currentObject = rootObject;
  378. Object parentObject = null;
  379. Segment lastSegment = segments[segments.length - 1];
  380. for (int i = 0; i < segments.length; ++i) {
  381. if (i == segments.length - 1) {
  382. parentObject = currentObject;
  383. break;
  384. }
  385. Segment segement = segments[i];
  386. if (i == segments.length - 2
  387. && lastSegment instanceof FilterSegment
  388. && segement instanceof PropertySegment
  389. ) {
  390. FilterSegment filterSegment = (FilterSegment) lastSegment;
  391. if (currentObject instanceof List) {
  392. PropertySegment propertySegment = (PropertySegment) segement;
  393. List list = (List) currentObject;
  394. for (Iterator it = list.iterator();it.hasNext();) {
  395. Object item = it.next();
  396. Object result = propertySegment.eval(this, rootObject, item);
  397. if (result instanceof Iterable) {
  398. filterSegment.remove(this, rootObject, result);
  399. } else if (result instanceof Map) {
  400. if (filterSegment.filter.apply(this, rootObject, currentObject, result)) {
  401. it.remove();
  402. }
  403. }
  404. }
  405. return true;
  406. } else if (currentObject instanceof Map) {
  407. PropertySegment propertySegment = (PropertySegment) segement;
  408. Object result = propertySegment.eval(this, rootObject, currentObject);
  409. if (result == null) {
  410. return false;
  411. }
  412. if (result instanceof Map
  413. && filterSegment.filter.apply(this, rootObject, currentObject, result)) {
  414. propertySegment.remove(this, currentObject);
  415. return true;
  416. }
  417. }
  418. }
  419. currentObject = segement.eval(this, rootObject, currentObject);
  420. if (currentObject == null) {
  421. break;
  422. }
  423. }
  424. if (parentObject == null) {
  425. return false;
  426. }
  427. if (lastSegment instanceof PropertySegment) {
  428. PropertySegment propertySegment = (PropertySegment) lastSegment;
  429. if (parentObject instanceof Collection) {
  430. if (segments.length > 1) {
  431. Segment parentSegment = segments[segments.length - 2];
  432. if (parentSegment instanceof RangeSegment || parentSegment instanceof MultiIndexSegment) {
  433. Collection collection = (Collection) parentObject;
  434. boolean removedOnce = false;
  435. for (Object item : collection) {
  436. boolean removed = propertySegment.remove(this, item);
  437. if (removed) {
  438. removedOnce = true;
  439. }
  440. }
  441. return removedOnce;
  442. }
  443. }
  444. }
  445. return propertySegment.remove(this, parentObject);
  446. }
  447. if (lastSegment instanceof ArrayAccessSegment) {
  448. return ((ArrayAccessSegment) lastSegment).remove(this, parentObject);
  449. }
  450. if (lastSegment instanceof FilterSegment) {
  451. FilterSegment filterSegment = (FilterSegment) lastSegment;
  452. return filterSegment.remove(this, rootObject, parentObject);
  453. }
  454. throw new UnsupportedOperationException();
  455. }
  456. public boolean set(Object rootObject, Object value) {
  457. return set(rootObject, value, true);
  458. }
  459. public boolean set(Object rootObject, Object value, boolean p) {
  460. if (rootObject == null) {
  461. return false;
  462. }
  463. init();
  464. Object currentObject = rootObject;
  465. Object parentObject = null;
  466. for (int i = 0; i < segments.length; ++i) {
  467. // if (i == segments.length - 1) {
  468. // parentObject = currentObject;
  469. // break;
  470. // }
  471. //
  472. parentObject = currentObject;
  473. Segment segment = segments[i];
  474. currentObject = segment.eval(this, rootObject, currentObject);
  475. if (currentObject == null) {
  476. Segment nextSegment = null;
  477. if (i < segments.length - 1) {
  478. nextSegment = segments[i + 1];
  479. }
  480. Object newObj = null;
  481. if (nextSegment instanceof PropertySegment) {
  482. JavaBeanDeserializer beanDeserializer = null;
  483. Class<?> fieldClass = null;
  484. if (segment instanceof PropertySegment) {
  485. String propertyName = ((PropertySegment) segment).propertyName;
  486. Class<?> parentClass = parentObject.getClass();
  487. JavaBeanDeserializer parentBeanDeserializer = getJavaBeanDeserializer(parentClass);
  488. if (parentBeanDeserializer != null) {
  489. FieldDeserializer fieldDeserializer = parentBeanDeserializer.getFieldDeserializer(propertyName);
  490. fieldClass = fieldDeserializer.fieldInfo.fieldClass;
  491. beanDeserializer = getJavaBeanDeserializer(fieldClass);
  492. }
  493. }
  494. if (beanDeserializer != null) {
  495. if (beanDeserializer.beanInfo.defaultConstructor != null) {
  496. newObj = beanDeserializer.createInstance(null, fieldClass);
  497. } else {
  498. return false;
  499. }
  500. } else {
  501. newObj = new JSONObject();
  502. }
  503. } else if (nextSegment instanceof ArrayAccessSegment) {
  504. newObj = new JSONArray();
  505. }
  506. if (newObj != null) {
  507. if (segment instanceof PropertySegment) {
  508. PropertySegment propSegement = (PropertySegment) segment;
  509. propSegement.setValue(this, parentObject, newObj);
  510. currentObject = newObj;
  511. continue;
  512. } else if (segment instanceof ArrayAccessSegment) {
  513. ArrayAccessSegment arrayAccessSegement = (ArrayAccessSegment) segment;
  514. arrayAccessSegement.setValue(this, parentObject, newObj);
  515. currentObject = newObj;
  516. continue;
  517. }
  518. }
  519. break;
  520. }
  521. }
  522. if (parentObject == null) {
  523. return false;
  524. }
  525. Segment lastSegment = segments[segments.length - 1];
  526. if (lastSegment instanceof PropertySegment) {
  527. PropertySegment propertySegment = (PropertySegment) lastSegment;
  528. propertySegment.setValue(this, parentObject, value);
  529. return true;
  530. }
  531. if (lastSegment instanceof ArrayAccessSegment) {
  532. return ((ArrayAccessSegment) lastSegment).setValue(this, parentObject, value);
  533. }
  534. throw new UnsupportedOperationException();
  535. }
  536. public static Object eval(Object rootObject, String path) {
  537. JSONPath jsonpath = compile(path);
  538. return jsonpath.eval(rootObject);
  539. }
  540. public static Object eval(Object rootObject, String path, boolean ignoreNullValue) {
  541. JSONPath jsonpath = compile(path, ignoreNullValue);
  542. return jsonpath.eval(rootObject);
  543. }
  544. public static int size(Object rootObject, String path) {
  545. JSONPath jsonpath = compile(path);
  546. Object result = jsonpath.eval(rootObject);
  547. return jsonpath.evalSize(result);
  548. }
  549. /**
  550. * Compile jsonPath and use it to extract keySet or field names from rootObject.
  551. *
  552. * @param rootObject Can be a map or custom object. Array and Collection are not supported.
  553. * @param path JSONPath string to be compiled.
  554. * @return Set of keys, or <code>null</code> if not supported.
  555. */
  556. public static Set<?> keySet(Object rootObject, String path) {
  557. JSONPath jsonpath = compile(path);
  558. Object result = jsonpath.eval(rootObject);
  559. return jsonpath.evalKeySet(result);
  560. }
  561. public static boolean contains(Object rootObject, String path) {
  562. if (rootObject == null) {
  563. return false;
  564. }
  565. JSONPath jsonpath = compile(path);
  566. return jsonpath.contains(rootObject);
  567. }
  568. public static boolean containsValue(Object rootObject, String path, Object value) {
  569. JSONPath jsonpath = compile(path);
  570. return jsonpath.containsValue(rootObject, value);
  571. }
  572. public static void arrayAdd(Object rootObject, String path, Object... values) {
  573. JSONPath jsonpath = compile(path);
  574. jsonpath.arrayAdd(rootObject, values);
  575. }
  576. public static boolean set(Object rootObject, String path, Object value) {
  577. JSONPath jsonpath = compile(path);
  578. return jsonpath.set(rootObject, value);
  579. }
  580. public static boolean remove(Object root, String path) {
  581. JSONPath jsonpath = compile(path);
  582. return jsonpath.remove(root);
  583. }
  584. public static JSONPath compile(String path) {
  585. if (path == null) {
  586. throw new JSONPathException("jsonpath can not be null");
  587. }
  588. JSONPath jsonpath = pathCache.get(path);
  589. if (jsonpath == null) {
  590. jsonpath = new JSONPath(path);
  591. if (pathCache.size() < 1024) {
  592. pathCache.putIfAbsent(path, jsonpath);
  593. jsonpath = pathCache.get(path);
  594. }
  595. }
  596. return jsonpath;
  597. }
  598. public static JSONPath compile(String path, boolean ignoreNullValue) {
  599. if (path == null) {
  600. throw new JSONPathException("jsonpath can not be null");
  601. }
  602. JSONPath jsonpath = pathCache.get(path);
  603. if (jsonpath == null) {
  604. jsonpath = new JSONPath(path, ignoreNullValue);
  605. if (pathCache.size() < 1024) {
  606. pathCache.putIfAbsent(path, jsonpath);
  607. jsonpath = pathCache.get(path);
  608. }
  609. }
  610. return jsonpath;
  611. }
  612. /**
  613. * @since 1.2.9
  614. * @param json
  615. * @param path
  616. * @return
  617. */
  618. public static Object read(String json, String path) {
  619. return compile(path)
  620. .eval(
  621. JSON.parse(json)
  622. );
  623. }
  624. /**
  625. * @since 1.2.76
  626. * @param json
  627. * @param path
  628. * @param clazz
  629. * @param parserConfig
  630. * @return
  631. */
  632. public static <T> T read(String json, String path, Type clazz, ParserConfig parserConfig) {
  633. return compile(path).eval(JSON.parse(json), clazz, parserConfig);
  634. }
  635. /**
  636. * @since 1.2.76
  637. * @param json
  638. * @param path
  639. * @param clazz
  640. * @return
  641. */
  642. public static <T> T read(String json, String path, Type clazz) {
  643. return read(json, path, clazz, null);
  644. }
  645. /**
  646. * @since 1.2.51
  647. * @param json
  648. * @param path
  649. * @return
  650. */
  651. public static Object extract(String json, String path, ParserConfig config, int features, Feature... optionFeatures) {
  652. features |= Feature.OrderedField.mask;
  653. DefaultJSONParser parser = new DefaultJSONParser(json, config, features);
  654. JSONPath jsonPath = compile(path);
  655. Object result = jsonPath.extract(parser);
  656. parser.lexer.close();
  657. return result;
  658. }
  659. public static Object extract(String json, String path) {
  660. return extract(json, path, ParserConfig.global, JSON.DEFAULT_PARSER_FEATURE);
  661. }
  662. public static Map<String, Object> paths(Object javaObject) {
  663. return paths(javaObject, SerializeConfig.globalInstance);
  664. }
  665. public static Map<String, Object> paths(Object javaObject, SerializeConfig config) {
  666. Map<Object, String> values = new IdentityHashMap<Object, String>();
  667. Map<String, Object> paths = new HashMap<String, Object>();
  668. paths(values, paths, "/", javaObject, config);
  669. return paths;
  670. }
  671. private static void paths(Map<Object, String> values, Map<String, Object> paths, String parent, Object javaObject, SerializeConfig config) {
  672. if (javaObject == null) {
  673. return;
  674. }
  675. String p = values.put(javaObject, parent);
  676. if (p != null) {
  677. Class<?> type = javaObject.getClass();
  678. boolean basicType = type == String.class
  679. || type == Boolean.class
  680. || type == Character.class
  681. || type == UUID.class
  682. || type.isEnum()
  683. || javaObject instanceof Number
  684. || javaObject instanceof Date
  685. ;
  686. if (!basicType) {
  687. return;
  688. }
  689. }
  690. paths.put(parent, javaObject);
  691. if (javaObject instanceof Map) {
  692. Map map = (Map) javaObject;
  693. for (Object entryObj : map.entrySet()) {
  694. Map.Entry entry = (Map.Entry) entryObj;
  695. Object key = entry.getKey();
  696. if (key instanceof String) {
  697. String path = parent.equals("/") ? "/" + key : parent + "/" + key;
  698. paths(values, paths, path, entry.getValue(), config);
  699. }
  700. }
  701. return;
  702. }
  703. if (javaObject instanceof Collection) {
  704. Collection collection = (Collection) javaObject;
  705. int i = 0;
  706. for (Object item : collection) {
  707. String path = parent.equals("/") ? "/" + i : parent + "/" + i;
  708. paths(values, paths, path, item, config);
  709. ++i;
  710. }
  711. return;
  712. }
  713. Class<?> clazz = javaObject.getClass();
  714. if (clazz.isArray()) {
  715. int len = Array.getLength(javaObject);
  716. for (int i = 0; i < len; ++i) {
  717. Object item = Array.get(javaObject, i);
  718. String path = parent.equals("/") ? "/" + i : parent + "/" + i;
  719. paths(values, paths, path, item, config);
  720. }
  721. return;
  722. }
  723. if (ParserConfig.isPrimitive2(clazz) || clazz.isEnum()) {
  724. return;
  725. }
  726. ObjectSerializer serializer = config.getObjectWriter(clazz);
  727. if (serializer instanceof JavaBeanSerializer) {
  728. JavaBeanSerializer javaBeanSerializer = (JavaBeanSerializer) serializer;
  729. try {
  730. Map<String, Object> fieldValues = javaBeanSerializer.getFieldValuesMap(javaObject);
  731. for (Map.Entry<String, Object> entry : fieldValues.entrySet()) {
  732. String key = entry.getKey();
  733. if (key instanceof String) {
  734. String path = parent.equals("/") ? "/" + key : parent + "/" + key;
  735. paths(values, paths, path, entry.getValue(), config);
  736. }
  737. }
  738. } catch (Exception e) {
  739. throw new JSONException("toJSON error", e);
  740. }
  741. return;
  742. }
  743. return;
  744. }
  745. public String getPath() {
  746. return path;
  747. }
  748. static class JSONPathParser {
  749. private final String path;
  750. private int pos;
  751. private char ch;
  752. private int level;
  753. private boolean hasRefSegment;
  754. private static final String strArrayRegex = "\'\\s*,\\s*\'";
  755. private static final Pattern strArrayPatternx = Pattern.compile(strArrayRegex);
  756. public JSONPathParser(String path){
  757. this.path = path;
  758. next();
  759. }
  760. void next() {
  761. ch = path.charAt(pos++);
  762. }
  763. char getNextChar() {
  764. return path.charAt(pos);
  765. }
  766. boolean isEOF() {
  767. return pos >= path.length();
  768. }
  769. Segment readSegement() {
  770. if (level == 0 && path.length() == 1) {
  771. if (isDigitFirst(ch)) {
  772. int index = ch - '0';
  773. return new ArrayAccessSegment(index);
  774. } else if ((ch >= 'a' && ch <= 'z') || ((ch >= 'A' && ch <= 'Z'))) {
  775. return new PropertySegment(Character.toString(ch), false);
  776. }
  777. }
  778. while (!isEOF()) {
  779. skipWhitespace();
  780. if (ch == '$') {
  781. next();
  782. skipWhitespace();
  783. if (ch == '?') {
  784. return new FilterSegment(
  785. (Filter) parseArrayAccessFilter(false));
  786. }
  787. continue;
  788. }
  789. if (ch == '.' || ch == '/') {
  790. int c0 = ch;
  791. boolean deep = false;
  792. next();
  793. if (c0 == '.' && ch == '.') {
  794. next();
  795. deep = true;
  796. if (path.length() > pos + 3
  797. && ch == '['
  798. && path.charAt(pos) == '*'
  799. && path.charAt(pos + 1) == ']'
  800. && path.charAt(pos + 2) == '.') {
  801. next();
  802. next();
  803. next();
  804. next();
  805. }
  806. }
  807. if (ch == '*' || (deep && ch == '[')) {
  808. boolean objectOnly = ch == '[';
  809. if (!isEOF()) {
  810. next();
  811. }
  812. if (deep) {
  813. if (objectOnly) {
  814. return WildCardSegment.instance_deep_objectOnly;
  815. } else {
  816. return WildCardSegment.instance_deep;
  817. }
  818. } else {
  819. return WildCardSegment.instance;
  820. }
  821. }
  822. if (isDigitFirst(ch)) {
  823. return parseArrayAccess(false);
  824. }
  825. String propertyName = readName();
  826. if (ch == '(') {
  827. next();
  828. if (ch == ')') {
  829. if (!isEOF()) {
  830. next();
  831. }
  832. if ("size".equals(propertyName) || "length".equals(propertyName)) {
  833. return SizeSegment.instance;
  834. } else if ("max".equals(propertyName)) {
  835. return MaxSegment.instance;
  836. } else if ("min".equals(propertyName)) {
  837. return MinSegment.instance;
  838. } else if ("keySet".equals(propertyName)) {
  839. return KeySetSegment.instance;
  840. } else if ("type".equals(propertyName)) {
  841. return TypeSegment.instance;
  842. } else if ("floor".equals(propertyName)) {
  843. return FloorSegment.instance;
  844. }
  845. throw new JSONPathException("not support jsonpath : " + path);
  846. }
  847. throw new JSONPathException("not support jsonpath : " + path);
  848. }
  849. return new PropertySegment(propertyName, deep);
  850. }
  851. if (ch == '[') {
  852. return parseArrayAccess(true);
  853. }
  854. if (level == 0) {
  855. String propertyName = readName();
  856. return new PropertySegment(propertyName, false);
  857. }
  858. if (ch == '?') {
  859. return new FilterSegment(
  860. (Filter) parseArrayAccessFilter(false));
  861. }
  862. throw new JSONPathException("not support jsonpath : " + path);
  863. }
  864. return null;
  865. }
  866. public final void skipWhitespace() {
  867. for (;;) {
  868. if (ch <= ' ' && (ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t' || ch == '\f' || ch == '\b')) {
  869. next();
  870. continue;
  871. } else {
  872. break;
  873. }
  874. }
  875. }
  876. Segment parseArrayAccess(boolean acceptBracket) {
  877. Object object = parseArrayAccessFilter(acceptBracket);
  878. if (object instanceof Segment) {
  879. return ((Segment) object);
  880. }
  881. return new FilterSegment((Filter) object);
  882. }
  883. Object parseArrayAccessFilter(boolean acceptBracket) {
  884. if (acceptBracket) {
  885. accept('[');
  886. }
  887. boolean predicateFlag = false;
  888. int lparanCount = 0;
  889. if (ch == '?') {
  890. next();
  891. accept('(');
  892. lparanCount++;
  893. while (ch == '(') {
  894. next();
  895. lparanCount++;
  896. }
  897. predicateFlag = true;
  898. }
  899. skipWhitespace();
  900. if (predicateFlag
  901. || IOUtils.firstIdentifier(ch)
  902. || Character.isJavaIdentifierStart(ch)
  903. || ch == '\\'
  904. || ch == '@') {
  905. boolean self = false;
  906. if (ch == '@') {
  907. next();
  908. accept('.');
  909. self = true;
  910. }
  911. String propertyName = readName();
  912. skipWhitespace();
  913. if (predicateFlag && ch == ')') {
  914. next();
  915. Filter filter = new NotNullSegement(propertyName, false);
  916. while (ch == ' ') {
  917. next();
  918. }
  919. if (ch == '&' || ch == '|') {
  920. filter = filterRest(filter);
  921. }
  922. if (acceptBracket) {
  923. accept(']');
  924. }
  925. return filter;
  926. }
  927. if (acceptBracket && ch == ']') {
  928. if (isEOF()) {
  929. if (propertyName.equals("last")) {
  930. return new MultiIndexSegment(new int[]{-1});
  931. }
  932. }
  933. next();
  934. Filter filter = new NotNullSegement(propertyName, false);
  935. while (ch == ' ') {
  936. next();
  937. }
  938. if (ch == '&' || ch == '|') {
  939. filter = filterRest(filter);
  940. }
  941. accept(')');
  942. if (predicateFlag) {
  943. accept(')');
  944. }
  945. if (acceptBracket) {
  946. accept(']');
  947. }
  948. return filter;
  949. }
  950. boolean function = false;
  951. skipWhitespace();
  952. if (ch == '(') {
  953. next();
  954. accept(')');
  955. skipWhitespace();
  956. function = true;
  957. }
  958. Operator op = readOp();
  959. skipWhitespace();
  960. if (op == Operator.BETWEEN || op == Operator.NOT_BETWEEN) {
  961. final boolean not = (op == Operator.NOT_BETWEEN);
  962. Object startValue = readValue();
  963. String name = readName();
  964. if (!"and".equalsIgnoreCase(name)) {
  965. throw new JSONPathException(path);
  966. }
  967. Object endValue = readValue();
  968. if (startValue == null || endValue == null) {
  969. throw new JSONPathException(path);
  970. }
  971. if (isInt(startValue.getClass()) && isInt(endValue.getClass())) {
  972. Filter filter = new IntBetweenSegement(propertyName
  973. , function
  974. , TypeUtils.longExtractValue((Number) startValue)
  975. , TypeUtils.longExtractValue((Number) endValue)
  976. , not);
  977. return filter;
  978. }
  979. throw new JSONPathException(path);
  980. }
  981. if (op == Operator.IN || op == Operator.NOT_IN) {
  982. final boolean not = (op == Operator.NOT_IN);
  983. accept('(');
  984. List<Object> valueList = new JSONArray();
  985. {
  986. Object value = readValue();
  987. valueList.add(value);
  988. for (;;) {
  989. skipWhitespace();
  990. if (ch != ',') {
  991. break;
  992. }
  993. next();
  994. value = readValue();
  995. valueList.add(value);
  996. }
  997. }
  998. boolean isInt = true;
  999. boolean isIntObj = true;
  1000. boolean isString = true;
  1001. for (Object item : valueList) {
  1002. if (item == null) {
  1003. if (isInt) {
  1004. isInt = false;
  1005. }
  1006. continue;
  1007. }
  1008. Class<?> clazz = item.getClass();
  1009. if (isInt && !(clazz == Byte.class || clazz == Short.class || clazz == Integer.class
  1010. || clazz == Long.class)) {
  1011. isInt = false;
  1012. isIntObj = false;
  1013. }
  1014. if (isString && clazz != String.class) {
  1015. isString = false;
  1016. }
  1017. }
  1018. if (valueList.size() == 1 && valueList.get(0) == null) {
  1019. Filter filter;
  1020. if (not) {
  1021. filter = new NotNullSegement(propertyName, function);
  1022. } else {
  1023. filter = new NullSegement(propertyName, function);
  1024. }
  1025. while (ch == ' ') {
  1026. next();
  1027. }
  1028. if (ch == '&' || ch == '|') {
  1029. filter = filterRest(filter);
  1030. }
  1031. accept(')');
  1032. if (predicateFlag) {
  1033. accept(')');
  1034. }
  1035. if (acceptBracket) {
  1036. accept(']');
  1037. }
  1038. return filter;
  1039. }
  1040. if (isInt) {
  1041. if (valueList.size() == 1) {
  1042. long value = TypeUtils.longExtractValue((Number) valueList.get(0));
  1043. Operator intOp = not ? Operator.NE : Operator.EQ;
  1044. Filter filter = new IntOpSegement(propertyName, function, value, intOp);
  1045. while (ch == ' ') {
  1046. next();
  1047. }
  1048. if (ch == '&' || ch == '|') {
  1049. filter = filterRest(filter);
  1050. }
  1051. accept(')');
  1052. if (predicateFlag) {
  1053. accept(')');
  1054. }
  1055. if (acceptBracket) {
  1056. accept(']');
  1057. }
  1058. return filter;
  1059. }
  1060. long[] values = new long[valueList.size()];
  1061. for (int i = 0; i < values.length; ++i) {
  1062. values[i] = TypeUtils.longExtractValue((Number) valueList.get(i));
  1063. }
  1064. Filter filter = new IntInSegement(propertyName, function, values, not);
  1065. while (ch == ' ') {
  1066. next();
  1067. }
  1068. if (ch == '&' || ch == '|') {
  1069. filter = filterRest(filter);
  1070. }
  1071. accept(')');
  1072. if (predicateFlag) {
  1073. accept(')');
  1074. }
  1075. if (acceptBracket) {
  1076. accept(']');
  1077. }
  1078. return filter;
  1079. }
  1080. if (isString) {
  1081. if (valueList.size() == 1) {
  1082. String value = (String) valueList.get(0);
  1083. Operator intOp = not ? Operator.NE : Operator.EQ;
  1084. Filter filter = new StringOpSegement(propertyName, function, value, intOp);
  1085. while (ch == ' ') {
  1086. next();
  1087. }
  1088. if (ch == '&' || ch == '|') {
  1089. filter = filterRest(filter);
  1090. }
  1091. accept(')');
  1092. if (predicateFlag) {
  1093. accept(')');
  1094. }
  1095. if (acceptBracket) {
  1096. accept(']');
  1097. }
  1098. return filter;
  1099. }
  1100. String[] values = new String[valueList.size()];
  1101. valueList.toArray(values);
  1102. Filter filter = new StringInSegement(propertyName, function, values, not);
  1103. while (ch == ' ') {
  1104. next();
  1105. }
  1106. if (ch == '&' || ch == '|') {
  1107. filter = filterRest(filter);
  1108. }
  1109. accept(')');
  1110. if (predicateFlag) {
  1111. accept(')');
  1112. }
  1113. if (acceptBracket) {
  1114. accept(']');
  1115. }
  1116. return filter;
  1117. }
  1118. if (isIntObj) {
  1119. Long[] values = new Long[valueList.size()];
  1120. for (int i = 0; i < values.length; ++i) {
  1121. Number item = (Number) valueList.get(i);
  1122. if (item != null) {
  1123. values[i] = TypeUtils.longExtractValue(item);
  1124. }
  1125. }
  1126. Filter filter = new IntObjInSegement(propertyName, function, values, not);
  1127. while (ch == ' ') {
  1128. next();
  1129. }
  1130. if (ch == '&' || ch == '|') {
  1131. filter = filterRest(filter);
  1132. }
  1133. accept(')');
  1134. if (predicateFlag) {
  1135. accept(')');
  1136. }
  1137. if (acceptBracket) {
  1138. accept(']');
  1139. }
  1140. return filter;
  1141. }
  1142. throw new UnsupportedOperationException();
  1143. }
  1144. if (ch == '\'' || ch == '"') {
  1145. String strValue = readString();
  1146. Filter filter = null;
  1147. if (op == Operator.RLIKE) {
  1148. filter = new RlikeSegement(propertyName, function, strValue, false);
  1149. } else if (op == Operator.NOT_RLIKE) {
  1150. filter = new RlikeSegement(propertyName, function, strValue, true);
  1151. } else if (op == Operator.LIKE || op == Operator.NOT_LIKE) {
  1152. while (strValue.indexOf("%%") != -1) {
  1153. strValue = strValue.replaceAll("%%", "%");
  1154. }
  1155. final boolean not = (op == Operator.NOT_LIKE);
  1156. int p0 = strValue.indexOf('%');
  1157. if (p0 == -1) {
  1158. if (op == Operator.LIKE) {
  1159. op = Operator.EQ;
  1160. } else {
  1161. op = Operator.NE;
  1162. }
  1163. filter = new StringOpSegement(propertyName, function, strValue, op);
  1164. } else {
  1165. String[] items = strValue.split("%");
  1166. String startsWithValue = null;
  1167. String endsWithValue = null;
  1168. String[] containsValues = null;
  1169. if (p0 == 0) {
  1170. if (strValue.charAt(strValue.length() - 1) == '%') {
  1171. containsValues = new String[items.length - 1];
  1172. System.arraycopy(items, 1, containsValues, 0, containsValues.length);
  1173. } else {
  1174. endsWithValue = items[items.length - 1];
  1175. if (items.length > 2) {
  1176. containsValues = new String[items.length - 2];
  1177. System.arraycopy(items, 1, containsValues, 0, containsValues.length);
  1178. }
  1179. }
  1180. } else if (strValue.charAt(strValue.length() - 1) == '%') {
  1181. if (items.length == 1) {
  1182. startsWithValue = items[0];
  1183. } else {
  1184. containsValues = items;
  1185. }
  1186. } else {
  1187. if (items.length == 1) {
  1188. startsWithValue = items[0];
  1189. } else if (items.length == 2) {
  1190. startsWithValue = items[0];