Home>

Java has its own js engine, which has been supported since java 1.6.Getting better and better.I'm familiar with js.So a bold idea,Why not use the built-in js engine for json conversion?This way we can avoid introducing other third party libraries.

Background:Java 6 provides support for executing scripting languages.This support comes from the jsr223 specification, and the corresponding package is javax.script. by default,Java 6 only supports javascript scripts. Its underlying implementation is mozilla rhino, which is a pure java implementation of javascript.

Except that openjdk does not come with a js engine, both sun/oracle support it.So you can do it exactly.

I did this myself early.It's just that the performance of the earlier 1.6/1.7 rhino is poor.But at 1.8 performance is no longer the same.-Because it has been upgraded to the nashorn engine, a very fast js engine implementation.also,The code I wrote before is cumbersome.Although refactored a few times,But still poor writing.So now I want to change it,Change to a slightly "brighter" version. Please see the official code below,Its role is to convert a json string into a java map or list.

import java.util.list;
import java.util.map;
import javax.script.scriptengine;
import javax.script.scriptenginemanager;
import javax.script.scriptexception;
/**
 * json to java object utility class
 *
 * @author frank
 *
 * /
public class json {
  /**
   * Create a js engine factory,Supports rhino for java 6/7 and nashorn for java 8
   *
   * @return js engine
   * /
  public static scriptengine enginefatory () {
    return new scriptenginemanager ()
        .getenginebyname (system.getproperty ("java.version"). contains ("1.8.")?"nashorn":"rhino");
  }
  /**
   * jvm's built-in js engine
   * /
  private final static scriptengine engine=enginefatory ();
  /**
   * Read the map in json
   *
   * @param js
   * json string
   * @param key
   * json path, with aa.bb.cc
   * @return map object
   * /
  @suppresswarnings ("unchecked")
  public static map<string, object>getmap (string js, string key) {
    return (map<string, object>) accessmember (js, key, map.class);
  }
  /**
   * Read the map in json
   *
   * @param js
   * json string
   * @return map object
   * /
  public static map<string, object>getmap (string js) {
    return getmap (js, null);
  }
  /**
   * Convert to map or list
   *
   * @param js
   * json string
   * @param key
   * json path, with aa.bb.cc
   * @param clazz
   * Goal type
   * @return Audience
   * /
  @suppresswarnings ("unchecked")
  public static<t>t accessmember (string js, string key, class<t>clazz) {
    t result=null;
    try {
      engine.eval ("var obj =" + js);//rhino cannot return map directly, such as eval ("{a:1}")
                      //->null, you must add variables,For example, execute var xx =
                      //{...};
      object obj;
      if (key == null) {
        obj=engine.eval ("obj;");
      } else {
        if (key.contains (".")) {
          obj=engine.eval ("obj." + key + ";");
        } else {
          obj=engine.eval ("obj [" "+ key +" "];");
        }
      }
      result=(t) obj;
    } catch (scriptexception e) {
      system.err.println ("Script eval () operation exception! eval code:" + js);
      e.printstacktrace ();
    }
    return result;
  }
  /**
   * Read the list in json, each of the list is a map
   *
   * @param js
   * json string
   * @param key
   * json path, with aa.bb.cc
   * @return contains a list of maps
   * /
  @suppresswarnings ("unchecked")
  public static list<map<string, object>>getlist (string js, string key) {
    return (list<map<string, object>>) accessmember (js, key, list.class);
  }
  /**
   * Read the list in json, each of the list is a map
   *
   * @param js
   * json string
   * @return contains a list of maps
   * /
  public static list<map<string, object>>getlist (string js) {
    return getlist (js, null);
  }
  /**
   * Read the list in json, each of the list is a string
   *
   * @param js
   * json string
   * @param key
   * json path, with aa.bb.cc
   * @return contains a list of strings
   * /
  @suppresswarnings ("unchecked")
  public static list<string>getstringlist (string js, string key) {
    return (list<string>) accessmember (js, key, list.class);
  }
  /**
   * Read the list in json, each of the list is a string
   *
   * @param js
   * json string
   * @return contains a list of strings
   * /
  public static list<string>getstringlist (string js) {
    return getstringlist (js, null);
  }
  /**
   * js number is a double type, which is not convenient to use in java.
Convert it to int
   *
   * @param d
   * js number
   * @return int value
   * /
  public static int double2int (double d) {
    if (d>integer.max_value) {
      system.out.println (d + "The value is too large.
Do not apply this method to conversion to int ");
      return 0;
    } else {
      return d.intvalue ();
    }
  }
}

It's actually very convenient to use! The js object itself is a map structure, and the rhino native object nativeobject is the counterpart of the js object in the java language.It has implemented the map interface, so you can use nativeobjects as maps! Just type conversion! eval () returns an object. If you can determine that the object type is nativeobject, you can directly convert (map) object-then use methods such as get, even in jsp pages.

The same goes for list.

Below is the code for a single test.

import java.util.list;
import java.util.map;
import org.junit.test;
import com.ajaxjs.util.json.json;
import static org.junit.assert. *;
public class testjson {
  @test
  public void testgetmap () {
    map<string, object>map;
    map=json.getmap ("{a:" hello ", b:" world! ", c:{d:" nice! "}}");
    system.out.println (map.get ("a"));
    assertnotnull (map);
    map=json.getmap ("{a:" hello ", b:" world! ", c:{d:" nice! "}}", "c");
    system.out.println (map.get ("d"));
    assertnotnull (map);
    map=json.getmap ("{a:" hello ", b:" world! ", c:{d:" nice! ", e:{f:" fff "}}}", "c.e");
    system.out.println (map.get ("f"));
    assertnotnull (map);
  }
  @test
  public void testgetlistmap () {
    list<map<string, object>&list;
    list=json.getlist ("[{a:" hello "}, 123, true]");
    system.out.println (list.get (0) .get ("a"));
    asserttrue (list.size ()>0);
    list=json.getlist ("[{a:" hello "}, {b:" world! "}, {c:{d:" nice! "}}]");
    system.out.println (list.get (0) .get ("a"));
    asserttrue (list.size ()>0);
    list=json.getlist ("{a:" hello ", b:" world! ", c:[{d:" nice !!! "}]}", "c");
    system.out.println (list.get (0) .get ("d"));
  }
  @test
  public void testgetliststring () {
    list<string>list;
    list=json.getstringlist ("[" a "," b "," c "]");
    system.out.println (list.get (0));
    asserttrue (list.size ()>0);
    list=json.getstringlist ("[1," b "," c "]");
    system.out.println (list.get (1));
    asserttrue (list.size ()>0);
  }
}

It is worth noting thatAlthough jsengine provides a map interface, it can only be read.If you perform a map.put (key, value) operation on it, an unsupportoperation exception will be thrown.

  • Previous The hover method in jQuery with the css hover selector to achieve the highlighted element selection method
  • Next JQuery to achieve picture carousel effect