java - Jackson API: partially update a string -


i have complex json object string:

{ "a": ..., "b":..., /* lots of other properties */ "z":... } 

that read partially jackson , map java class:

class partialobjectforb { @jsonproperty("b") private objectb b; } 

i use readvalue() method objectmapper class , want... far, good.

now, want update values in partialobjectforb , update initial string had. figured how update java object jackson (by using readerforupdating) can't find how opposite: update json object/string java object.

i know how solve problem using jsonobject. example, if want update 1 value:

jsonobject j = new jsonobject(/* full json string */); j.getjsonobject("b").getjsonobject("bb")/* etc. */.put("bbbb", 4); j.tostring(); // give me full original text "b" updated. 

but can't find how jackson.

any idea?

notes:

  • my input/output strings, can't change that.
  • i don't know data in json object. know may have property "b" , if don't can create it.
  • i may want deserialize , update more 1 property @ root level (e.g: "b", "h" , "w").
  • this problem not recursive. meaning: have full representation of values unserialize (no unknown properties).
  • the json object, string, made of few thousand bytes, piece(s) want update lot smaller (e.g: around 100 bytes).

full executable source benchmark included is:

import java.io.ioexception; import java.io.stringwriter; import java.util.iterator; import java.util.map.entry; import java.util.random; import org.apache.commons.lang3.randomstringutils; import org.apache.commons.lang3.stringutils; import org.codehaus.jackson.jsongenerationexception; import org.codehaus.jackson.jsongenerator; import org.codehaus.jackson.jsonnode; import org.codehaus.jackson.version; import org.codehaus.jackson.annotate.jsonproperty; import org.codehaus.jackson.map.deserializationconfig; import org.codehaus.jackson.map.jsonmappingexception; import org.codehaus.jackson.map.jsonserializer; import org.codehaus.jackson.map.module; import org.codehaus.jackson.map.objectmapper; import org.codehaus.jackson.map.serializationconfig; import org.codehaus.jackson.map.serializerprovider; import org.codehaus.jackson.map.introspect.basicbeandescription; import org.codehaus.jackson.map.ser.beanpropertywriter; import org.codehaus.jackson.map.ser.std.beanserializerbase; import org.codehaus.jackson.node.objectnode; import org.json.jsonexception; import org.json.jsonobject;  public class jacksonmodule {      private static final objectmapper mapper = new objectmapper();     private static final int count = 0;     private static final int repeat_header = 40;      static {         mapper.configure(deserializationconfig.feature.fail_on_unknown_properties, false);         mapper.configure(serializationconfig.feature.write_null_properties, false);         mapper.registermodule(new mymodule());     }     private dataprocessor sdp;     private long[] sum = new long[5];      public static void main(string[] args) throws ioexception, jsonexception {         new jacksonmodule().start();     }      public jacksonmodule() throws ioexception, jsonexception {         this.sdp = new dataprocessor();     }      public void start() throws ioexception, jsonexception {         run(-1, false); // load classes: slow         if (count > 0) {             (int = 0; < count; ++i) {                 if (i % repeat_header == 0) {                     system.out.println("---------------------------------------------------------------------------------------");                     print("", "ro jsonobject", "ro jackson", "r/- jackson", "r/w jsonobject", "r/w jackson");                     system.out.println("---------------------------------------------------------------------------------------");                 }                 run(i, true);             }             system.out.println("-- average ----------------------------------------------------------------------------");             print(1, sum[0] / count, sum[1] / count, sum[2] / count, sum[3] / count, sum[4] / count);             system.out.println("---------------------------------------------------------------------------------------");             print("", "ro jsonobject", "ro jackson", "r/- jackson", "r/w jsonobject", "r/w jackson");             system.out.println("---------------------------------------------------------------------------------------");         }     }      public void run(int i, boolean print) throws jsonexception, ioexception {         long t1 = sdp.doreadwithjsonobject();         long t2 = sdp.doreadwithjackson();         long t3 = sdp.doreadforupdatingwithjacksonbutdontwrite();         long t4 = sdp.dosomewritingwithjsonobject();         long t5 = sdp.dosomewritingwithjackson();         if (print) {             print(i, t1, t2, t3, t4, t5);             sum[0] += t1;             sum[1] += t2;             sum[2] += t3;             sum[3] += t4;             sum[4] += t5;         }     }      private void print(int index, long t1, long t2, long t3, long t4, long t5) {         print(integer.tostring(index), string.format("%,d", t1), string.format("%,d", t2), string.format("%,d", t3), string.format("%,d", t4), string.format("%,d", t5));     }      private void print(string i0, string a, string b, string c, string d, string e) {         system.out.println("|"                 + stringutils.leftpad(i0, 5) + "|"                 + stringutils.leftpad(a, 15) + "|"                 + stringutils.leftpad(b, 15) + "|"                 + stringutils.leftpad(c, 15) + "|"                 + stringutils.leftpad(d, 15) + "|"                 + stringutils.leftpad(e, 15) + "|");     }      private static class dataprocessor {          private datastore store;         private long t0, t1;          private dataprocessor() throws ioexception, jsonexception {             this.store = new datastore(customer, browser);         }          public long doreadwithjsonobject() throws jsonexception {             t0 = system.nanotime();             jsonobject json = new jsonobject(store.readdata(null)); // can throw jsonexception             jsonobject customer = json.getjsonobject("customer");  // can throw jsonexception             jsonobject browserinfo = json.getjsonobject("browser");  // can throw jsonexception             // need manually mapping , figure out in object. hell no!             t1 = system.nanotime();             return t1 - t0;         }          public long doreadwithjackson() throws ioexception {             t0 = system.nanotime();             knownpart obj = store.readdata(null, knownpart.class);             t1 = system.nanotime();             return t1 - t0;         }          public long doreadforupdatingwithjacksonbutdontwrite() throws ioexception {             t0 = system.nanotime();             knownpart obj = store.readdataforupdating(null, knownpart.class);             t1 = system.nanotime();             return t1 - t0;         }          public long dosomewritingwithjsonobject() throws jsonexception {             t0 = system.nanotime();             jsonobject json = new jsonobject(store.readdata(null)); // can throw jsonexception             jsonobject customer = json.getjsonobject("customer");  // can throw jsonexception             jsonobject browserinfo = json.getjsonobject("browser");  // can throw jsonexception             customer.put("name", "jackson doe");             browserinfo.put("version", "10");             store.savedata(json);             t1 = system.nanotime();             return t1 - t0;         }          public long dosomewritingwithjackson() throws ioexception {             t0 = system.nanotime();             knownpart obj = store.readdataforupdating(null, knownpart.class);             obj.customer.name = "jackson doe";             obj.browser.version = "10";             store.savedata(obj);             t1 = system.nanotime();             return t1 - t0;         }     }      private static class datastore {          private final string data;          private datastore(customer customer, browserinfo browser) throws ioexception, jsonexception {             stringwriter sw = new stringwriter(1000);             try (jsongenerator jgen = mapper.getjsonfactory().createjsongenerator(sw)) {                 jgen.writestartobject();                 writebunchofproperties(jgen);                 jgen.writefieldname("customer");                 jgen.writerawvalue(mapper.writevalueasstring(customer));                 writebunchofproperties(jgen);                 jgen.writefieldname("browser");                 jgen.writerawvalue(mapper.writevalueasstring(browser));                 writebunchofproperties(jgen);                 jgen.writeendobject();             }             this.data = sw.tostring();         }          private void writebunchofproperties(jsongenerator jgen) throws ioexception {             int c = new random().nextint(3) + 1;             (int = 0; < c; ++i) {                 jgen.writefieldname(randomstringutils.random(10));                 jgen.writerawvalue(json_long);             }         }          public string readdata(string query) {             return data;         }          private void savedata(string json) {             // todo         }          public void savedata(jsonobject json) {             savedata(json.tostring());         }          public void savedata(object obj) throws ioexception {             savedata(mapper.writevalueasstring(obj));         }          public <t> t readdata(string query, class<t> clazz) throws ioexception {             return mapper.readvalue(readdata(query), clazz);         }          public <t extends unknownpart> t readdataforupdating(string query, class<t> clazz) throws ioexception {             objectnode root = (objectnode) mapper.readtree(readdata(query));             t obj = mapper.readvalue(root, clazz);             obj.tree = root;             return obj;         }     }      private static abstract class unknownpart {           objectnode tree;     }      private static class knownpart extends unknownpart {          @jsonproperty         private customer customer;         @jsonproperty         private browserinfo browser;     }      private static class customer {          @jsonproperty         private int id;         @jsonproperty         private string name;         @jsonproperty         private address[] addresses; // make more complex example          public customer(int id, string name, address[] addresses) {             this.id = id;             this.name = name;             this.addresses = addresses;         }          public customer() {         }     }      private static class address {          @jsonproperty         private string street;         @jsonproperty         private string city;          public address(string street, string city) {             this.street = street;             this.city = city;         }          public address() {         }     }      private static class browserinfo {          @jsonproperty         private string agent;         @jsonproperty         private string version;          public browserinfo(string agent, string version) {             this.agent = agent;             this.version = version;         }          public browserinfo() {         }     }      private static class mymodule extends module {          @override         public string getmodulename() {             return "mymodule";         }          @override         public version version() {             return new version(0, 0, 1, "snapshot");         }          @override         public void setupmodule(module.setupcontext context) {             context.addbeanserializermodifier(new org.codehaus.jackson.map.ser.beanserializermodifier() {                 private unknownpartserializer cs;                  @override                 public jsonserializer modifyserializer(serializationconfig config, basicbeandescription beandesc, jsonserializer<?> serializer) {                     return unknownpart.class.isassignablefrom(beandesc.getbeanclass())                        ? new unknownpartserializer((beanserializerbase) serializer)                        : serializer;                 }             });         }     }      private static class unknownpartserializer extends beanserializerbase {          public unknownpartserializer(beanserializerbase src) {             super(src);         }          @override         public void serialize(object bean, jsongenerator jgen, serializerprovider provider) throws ioexception, jsongenerationexception {             unknownpart = (unknownpart) bean;             jgen.writestartobject();             serializefields(up, jgen, provider);             jgen.writeendobject();         }          protected void serializefields(unknownpart bean, jsongenerator jgen, serializerprovider provider) throws ioexception, jsongenerationexception {             final beanpropertywriter[] props;             if (_filteredprops != null && provider.getserializationview() != null) {                 props = _filteredprops;             } else {                 props = _props;             }             int = 0;             try {                 (final int len = props.length; < len; ++i) {                     beanpropertywriter prop = props[i];                     if (prop != null) { // can have nulls in filtered list                         prop.serializeasfield(bean, jgen, provider);                         bean.tree.remove(prop.getname());                     }                 }                 if (_anygetterwriter != null) {                     _anygetterwriter.getandserialize(bean, jgen, provider);                 }                 iterator<entry<string, jsonnode>> = bean.tree.getfields();                 while (it.hasnext()) {                     entry<string, jsonnode> e = it.next();                     jgen.writefieldname(e.getkey());                     jgen.writeobject(e.getvalue());                 }             } catch (exception e) {                 string name = (i == props.length) ? "[anysetter]"                         : props[i].getname();                 wrapandthrow(provider, e, bean, name);             } catch (stackoverflowerror e) {                 /* 04-sep-2009, tatu: dealing tricky, since not                  *   have many stack frames spare... 1 or two; can't                  *   make many calls.                  */                 jsonmappingexception mape = new jsonmappingexception("infinite recursion (stackoverflowerror)", e);                 string name = (i == props.length) ? "[anysetter]"                         : props[i].getname();                 mape.prependpath(new jsonmappingexception.reference(bean, name));                 throw mape;             }         }     }     private static customer customer = new customer(1, "john doe", new address[]{         new address("broadway av", "new york"),         new address("peachtree st", "atlanta")     });     private static browserinfo browser = new browserinfo("ie", "6.0");     // json found on internet     private static final string json_long = "{\"web-app\": {"             + "\"servlet\": ["             + "{"             + "\"servlet-name\": \"cofaxcds\","             + "\"servlet-class\": \"org.cofax.cds.cdsservlet\","             + "\"init-param\": {"             + "\"configglossary:installationat\": \"philadelphia, pa\","             + "\"configglossary:adminemail\": \"ksm@pobox.com\","             + "\"configglossary:poweredby\": \"cofax\","             + "\"configglossary:poweredbyicon\": \"/images/cofax.gif\","             + "\"configglossary:staticpath\": \"/content/static\","             + "\"templateprocessorclass\": \"org.cofax.wysiwygtemplate\","             + "\"templateloaderclass\": \"org.cofax.filestemplateloader\","             + "\"templatepath\": \"templates\","             + "\"templateoverridepath\": \"\","             + "\"defaultlisttemplate\": \"listtemplate.htm\","             + "\"defaultfiletemplate\": \"articletemplate.htm\","             + "\"usejsp\": false,"             + "\"jsplisttemplate\": \"listtemplate.jsp\","             + "\"jspfiletemplate\": \"articletemplate.jsp\","             + "\"cachepackagetagstrack\": 200,"             + "\"cachepackagetagsstore\": 200,"             + "\"cachepackagetagsrefresh\": 60,"             + "\"cachetemplatestrack\": 100,"             + "\"cachetemplatesstore\": 50,"             + "\"cachetemplatesrefresh\": 15,"             + "\"cachepagestrack\": 200,"             + "\"cachepagesstore\": 100,"             + "\"cachepagesrefresh\": 10,"             + "\"cachepagesdirtyread\": 10,"             + "\"searchenginelisttemplate\": \"forsearchengineslist.htm\","             + "\"searchenginefiletemplate\": \"forsearchengines.htm\","             + "\"searchenginerobotsdb\": \"web-inf/robots.db\","             + "\"usedatastore\": true,"             + "\"datastoreclass\": \"org.cofax.sqldatastore\","             + "\"redirectionclass\": \"org.cofax.sqlredirection\","             + "\"datastorename\": \"cofax\","             + "\"datastoredriver\": \"com.microsoft.jdbc.sqlserver.sqlserverdriver\","             + "\"datastoreurl\": \"jdbc:microsoft:sqlserver://localhost:1433;databasename=goon\","             + "\"datastoreuser\": \"sa\","             + "\"datastorepassword\": \"datastoretestquery\","             + "\"datastoretestquery\": \"set nocount on;select test='test';\","             + "\"datastorelogfile\": \"/usr/local/tomcat/logs/datastore.log\","             + "\"datastoreinitconns\": 10,"             + "\"datastoremaxconns\": 100,"             + "\"datastoreconnusagelimit\": 100,"             + "\"datastoreloglevel\": \"debug\","             + "\"maxurllength\": 500}},"             + "{"             + "\"servlet-name\": \"cofaxemail\","             + "\"servlet-class\": \"org.cofax.cds.emailservlet\","             + "\"init-param\": {"             + "\"mailhost\": \"mail1\","             + "\"mailhostoverride\": \"mail2\"}},"             + "{"             + "\"servlet-name\": \"cofaxadmin\","             + "\"servlet-class\": \"org.cofax.cds.adminservlet\"},"             + ""             + "{"             + "\"servlet-name\": \"fileservlet\","             + "\"servlet-class\": \"org.cofax.cds.fileservlet\"},"             + "{"             + "\"servlet-name\": \"cofaxtools\","             + "\"servlet-class\": \"org.cofax.cms.cofaxtoolsservlet\","             + "\"init-param\": {"             + "\"templatepath\": \"toolstemplates/\","             + "\"log\": 1,"             + "\"loglocation\": \"/usr/local/tomcat/logs/cofaxtools.log\","             + "\"logmaxsize\": \"\","             + "\"datalog\": 1,"             + "\"dataloglocation\": \"/usr/local/tomcat/logs/datalog.log\","             + "\"datalogmaxsize\": \"\","             + "\"removepagecache\": \"/content/admin/remove?cache=pages&id=\","             + "\"removetemplatecache\": \"/content/admin/remove?cache=templates&id=\","             + "\"filetransferfolder\": \"/usr/local/tomcat/webapps/content/filetransferfolder\","             + "\"lookincontext\": 1,"             + "\"admingroupid\": 4,"             + "\"betaserver\": true}}],"             + "\"servlet-mapping\": {"             + "\"cofaxcds\": \"/\","             + "\"cofaxemail\": \"/cofaxutil/aemail/*\","             + "\"cofaxadmin\": \"/admin/*\","             + "\"fileservlet\": \"/static/*\","             + "\"cofaxtools\": \"/tools/*\"},"             + ""             + "\"taglib\": {"             + "\"taglib-uri\": \"cofax.tld\","             + "\"taglib-location\": \"/web-inf/tlds/cofax.tld\"}}}"; } 

Comments

Popular posts from this blog

basic authentication with http post params android -

vb.net - Virtual Keyboard commands -

c++ - End of file on pipe magic during open -