I am dealing with json data fetched from twitter API
on PHP I normally do something like:
$data = json_decode($response);
and the $data would be STD class object
I want to do the same thing in Java.
I took a look at Gson, but I need a second argument which seems like I need to create a specific class for the fetched data.
The basic question is how can I convert JSON to Standard Java Object like in PHP (STD Class Object)
Thank You
Read it into a map using Jackson then you can access whatever data you want. For instance, if your json looks like this
{ "name":"blah",
"address": {
"line1": "1234 my street",
"city": "my city",
"state": "my state"
}
}
Then you could:
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> mystuff = mapper.readValue( jsonString, Map.class );
String name = (String)mystuff.get("name");
String city = ((Map<String, Object>)mystuff.get( "address" )).get( "city" );
If your JSON data does not follow a specific structure, don't use GSON, but a regular JSON library (like the one from json.org) that will give you an instance of a class like JSONObject, from which you can access data like jsonObject.getString("key").
There is no standard class object in Java and thus you need a class. You could dynamically create and compile the class at runtime but I doubt that's worth the trouble.
When json_encode doesn't exist on a PHP server, I use this:
<?php
if (!function_exists('json_encode'))
{
function json_encode($a=false)
{
if (is_null($a)) return 'null';
if ($a === false) return 'false';
if ($a === true) return 'true';
if (is_scalar($a))
{
if (is_float($a))
{
// Always use "." for floats.
return floatval(str_replace(",", ".", strval($a)));
}
if (is_string($a))
{
static $jsonReplaces = array(array("\\", "/", "\n", "\t", "\r", "\b", "\f", '"'), array('\\\\', '\\/', '\\n', '\\t', '\\r', '\\b', '\\f', '\"'));
return '"' . str_replace($jsonReplaces[0], $jsonReplaces[1], $a) . '"';
}
else
return $a;
}
$isList = true;
for ($i = 0, reset($a); $i < count($a); $i++, next($a))
{
if (key($a) !== $i)
{
$isList = false;
break;
}
}
$result = array();
if ($isList)
{
foreach ($a as $v) $result[] = json_encode($v);
return '[' . join(',', $result) . ']';
}
else
{
foreach ($a as $k => $v) $result[] = json_encode($k).':'.json_encode($v);
return '{' . join(',', $result) . '}';
}
}
}
?>
If you could rewrite this in Java then it should to the trick for you.
Ref:(Dead link)http://snippets.dzone.com/posts/show/7487
Related
In groovy, I have below object. (Type: [Ljava.lang.Object)
test = [
{
"id":"rod_1565173117796",
"userName":"rod",
"displayName":"Rod",
"date":1565173117796,
"comment":"ok"
},
{
"id":"rod_1565173139923",
"userName":"rod",
"displayName":"Rod",
"date":1565173139923,
"comment":"fine"
}
]
I want to modify / delete this list of JSON array based on id.
I tried below thing filter the required json object from list.
parsedJSON = parser.parseText(test);
parsedJSON.findAll{ it.id == 'rod_1565173139923' });
Which is giving me that
No such property: id for class: java.lang.String
What wrong i am doing?
Thanks!
just several syntax fixes and your code works:
def test = '''[
{
"id":"rod_1565173117796",
"userName":"rod",
"displayName":"Rod",
"date":1565173117796,
"comment":"ok"
},
{
"id":"rod_1565173139923",
"userName":"rod",
"displayName":"Rod",
"date":1565173139923,
"comment":"fine"
}
]'''
def parser = new groovy.json.JsonSlurper()
def parsedJSON = parser.parseText(test);
def filtered = parsedJSON.findAll{ it.id == 'rod_1565173139923' }
I am having a ccode, which bulids jsonfile in the below format.
{"swap":1,"si":11},{"system":1,host:"new"},{"Cpu":1}
If I validate this jsonfile data i get an error as:
Parse error on line 4:
...": 1, "si": 11},{ "system": 1,
---------------------^ Expecting 'EOF'
How to resolve this issue?
Wrap those jsonObjects in to an JsonArray while building. Then in java iterate through the jsonarray.
In jsonevery key is double quoted "key". Your jsonis missing double quotes at host key. Make sure you're writing a well-formed json.
{ "system": 1, "host": "new" }
^ ^
am not a expert in JSON but i think you want to change a JSON like array value
[{"swap":1,"si":11},{"system":1,host:"new"},{"Cpu":1}]
insted of
{"swap":1,"si":11},{"system":1,host:"new"},{"Cpu":1}
You can also use this custom function even if you have complex objects.
static getParsedJson(jsonString) {
const parsedJsonArr = [];
let tempStr = '';
let isObjStartFound = false;
for (let i = 0; i < jsonString.length; i += 1) {
if (isObjStartFound) {
tempStr += jsonString[i];
if (jsonString[i] === '}') {
try {
const obj = JSON.parse(tempStr);
parsedJsonArr.push(obj);
tempStr = '';
isObjStartFound = false;
} catch (err) {
// console.log("not a valid JSON object");
}
}
}
if (!isObjStartFound && jsonString[i] === '{') {
tempStr += jsonString[i];
isObjStartFound = true;
}
}
return parsedJsonArr;
}
I haved parse a JSON wich PHP in few minutes, it's very easy.
I need to do the same things in JAVA and it's more complicated.
I have choose Jackson.
Here the JSON:
{
"object":"page",
"entry":[
{
"id":"1849584656581184912",
"time":1361458605,
"changes":[
{
"field":"feed",
"value":{
"item":"post",
"verb":"add",
"post_id":"6022322264458251"
}
}
]
},
{
"id":"184965658184912",
"time":1361458606,
"changes":[
{
"field":"feed",
"value":{
"item":"comment",
"verb":"add",
"comment_id":"1849584656581184912_6022322264458251_7510038",
"parent_id":"1849584656581184912_6022322264458251",
"sender_id":657754651107,
"created_time":1361458606
}
},
{
"field":"feed",
"value":{
"item":"comment",
"verb":"add",
"comment_id":"1849584656581184912_6022322264458251_7510037",
"parent_id":"1849584656581184912_6022322264458251",
"sender_id":657754651107,
"created_time":1361458606
}
}
]
}
]
}
Here the PHP code:
foreach($object["entry"] as $update)
{
// For each entry in notification, display the entry
echo "page id = " . $update["id"];
echo "time = " . $update["time"];
foreach($update["changes"] as $change) {
echo "field = " . $change["field"];
echo "verb = " . $change["value"]["verb"];
if($change["value"]["item"] == "comment") {
echo "Nouveau commentaire publié !";
echo "comment_id = " . $change["value"]["comment_id"];
echo "parent_id = " . $change["value"]["parent_id"];
echo "sender_id = " . $change["value"]["sender_id"];
echo "created_time = " . $change["value"]["created_time"];
} else if($change["value"]["item"] == "post") {
echo "Nouveau post publié !";
echo "post_id = " . $change["value"]["post_id"];
}
}
}
So I need the same things, to parse this JSON and display some informations.
Do you know a simple way to do this, like in PHP?
Thanks
If you only want to access some fields directly then you should use JsonNodes.
ObjectMapper mapper = new ObjectMapper();
JsonNode root = mapper.readTree(jsonString);
JsonNode entry = root.get("entry");
…
Edit: Be sure to have a look on all concrete subclasses. For example an ArrayNode lets you iterate over all of its elements.
Same code as above with casts:
ObjectMapper mapper = new ObjectMapper();
ObjectNode root = (ObjectNode) Jsmapper.readTree(jsonString);
ArrayNode entry = (ArrayNode) root.get("entry");
…
I'm coming to Java from JavaScript/Ruby. Let's say I've got the following JSON object for an animal:
{
name: {
common: "Tiger",
latin: "Panthera tigris"
}
legs: 4
}
I'm dealing with lots of animal APIs, and I want to normalize them all into my own common format, like:
{
common_name: "Tiger",
latin_name: "Panthera tigris",
limbs: {
legs: 4,
arms: 0
}
}
In, say, JavaScript, this would be straightforward:
normalizeAnimal = function(original){
return {
common_name: original.name.common,
latin_name: original.name.latin,
limbs: {
legs: original.legs || 0,
arms: original.arms || 0
}
}
}
But what about in Java? Using the JSONObject class from org.json, I could go down the road of doing something like this:
public JSONObject normalizeAnimal(JSONObject original) throws JSONException{
JSONObject name = original.getJSONObject("name");
JSONObject limbs = new JSONObject();
JSONObject normalized = new JSONObject();
normalized.put("name_name", name.get("common"));
normalized.put("latin_name", name.get("latin"));
try{
limbs.put("legs", original.get("legs");
}catch(e){
limbs.put("legs", 0);
};
try{
limbs.put("arms", original.get("arms");
}catch(e){
limbs.put("arms", 0);
};
normalized.put("limbs", limbs);
return normalized;
}
This gets worse as the JSON objects I'm dealing with get longer and deeper. In addition to all of this, I'm dealing with many providers for animal objects and I'll eventually be looking to have some succinct configuration format for describing the transformations (like, maybe, "common_name": "name.common", "limbs.legs": "legs").
How would I go about making this suck less in Java?
Use a library like Gson or Jackson and map the JSON to a Java Object.
So you're going to have a bean like
public class JsonAnima {
private JsonName name;
private int legs;
}
public class JsonName {
private String commonName;
private String latinName;
}
which can be easily converted with any library with something like (with Jackson)
ObjectMapper mapper = new ObjectMapper();
JsonAnimal animal = mapper.readValue(jsonString, JsonAnimal.class);
then you can create a "converter" to map the JsonAnimal to you Animal class.
This can be a way of doing it. : )
Some links:
Gson: http://code.google.com/p/google-gson/
Jackson: http://wiki.fasterxml.com/JacksonHome
The pure Java solutions all are challenged to deal with unreliable structure of your source data. If you're running in a JVM, I recommend that you consider using Groovy to do the Parse and the Build of your source JSON. The result ends up looking a lot like the Javascript solution you outlined above:
import groovy.json.JsonBuilder
import groovy.json.JsonSlurper
def originals = [
'{ "name": { "common": "Tiger", "latin": "Panthera tigris" }, "legs": 4 }',
'{ "name": { "common": "Gecko", "latin": "Gek-onero" }, "legs": 4, "arms": 0 }',
'{ "name": { "common": "Liger" }, "legs": 4, "wings": 2 }',
'{ "name": { "common": "Human", "latin": "Homo Sapien" }, "legs": 2, "arms": 2 }'
]
originals.each { orig ->
def slurper = new JsonSlurper()
def parsed = slurper.parseText( orig )
def builder = new JsonBuilder()
// This builder looks a lot like the Javascript solution, no?
builder {
common_name parsed.name.common
latin_name parsed.name.latin
limbs {
legs parsed.legs ?: 0
arms parsed.arms ?: 0
}
}
def normalized = builder.toString()
println "$normalized"
}
Running the script above deals with "jagged" JSON (not all elements have the same attributes) and outputs like...
{"common_name":"Tiger","latin_name":"Panthera tigris","limbs":{"legs":4,"arms":0}}
{"common_name":"Gecko","latin_name":"Gek-onero","limbs":{"legs":4,"arms":0}}
{"common_name":"Liger","latin_name":null,"limbs":{"legs":4,"arms":0}}
{"common_name":"Human","latin_name":"Homo Sapien","limbs":{"legs":2,"arms":2}}
If you'll be using this for many different types of objects, I would suggest to use reflection instead of serializing each object manually. By using reflection you will not need to create methods like normalizeAnimal, you just create one method or one class to do the serialization to json format.
If you search for "mapping json java" you'll find some useful references. Like gson. Here is an example that is on their website:
class BagOfPrimitives {
private int value1 = 1;
private String value2 = "abc";
private transient int value3 = 3;
BagOfPrimitives() {
// no-args constructor
}
}
//(Serialization)
BagOfPrimitives obj = new BagOfPrimitives();
Gson gson = new Gson();
String json = gson.toJson(obj);
///==> json is {"value1":1,"value2":"abc"}
///Note that you can not serialize objects with circular references since that will result in infinite recursion.
//(Deserialization)
BagOfPrimitives obj2 = gson.fromJson(json, BagOfPrimitives.class);
//==> obj2 is just like obj
You can try little jmom java library
JsonValue json = JsonParser.parse(stringvariablewithjsoninside);
Jmom mom = Jmom.instance()
.copy("/name/common", "/common_name", true)
.copy("/name/latin", "/latin_name", true)
.copy("/arms", "/limbs/arms", true)
.copy("/legs", "/limbs/legs", true)
.remove("/name")
;
mom.apply(json);
String str = json.toPrettyString(" ");
The JSON string is as follows
{
"rank":"-text_relevance",
"match-expr":"(label 'star wars')",
"hits":{
"found":7,
"start":0,
"hit":[
{"id":"tt1185834",
"data":{
"actor":["Abercrombie, Ian","Baker, Dee","Burton, Corey"],
"title":["Star Wars: The Clone Wars"]
}
},
.
.
.
{"id":"tt0121766",
"data":{
"actor":["Bai, Ling","Bryant, Gene","Castle-Hughes, Keisha"],
"title":["Star Wars: Episode III - Revenge of the Sith"]
}
}
]
},
"info":{
"rid":"b7c167f6c2da6d93531b9a7b314ad030b3a74803b4b7797edb905ba5a6a08",
"time-ms":2,
"cpu-time-ms":0
}
}
It has many fields, but I just have want the Data field. This won't work:
mapper.readvalue(jsonString,Data.class);
How do I make Jackson read just the "Data" field?
Jackson 2.3 now has a JsonPointer class you can use. There's a simple example in their quick overview for the release.
Usage is simple: for JSON like
{
"address" : { "street" : "2940 5th Ave", "zip" : 980021 },
"dimensions" : [ 10.0, 20.0, 15.0 ]
}
you could use expressions like:
JsonNode root = mapper.readTree(src);
int zip =root.at("/address/zip").asIntValue();
double height = root.add("/dimensions/1").asDoubleValue();// assuming it's the second number in there
I think that the easiest way to do this is using the Jackson TreeModel: let Jackson parse the JSON input into a JsonNode object that you then query, assuming some knowledge of the data structure. This way you can ignore most of the data, walking down the JsonNodes to the data that you want.
// String input = The JSON data from your question
ObjectMapper mapper = new ObjectMapper();
JsonNode rootNode = mapper.readValue(input.getBytes(), JsonNode.class);
// can also use ArrayNode here, but JsonNode allows us to get(index) line an array:
JsonNode hits = rootNode.get("hits");
// can also use ObjectNodes here:
JsonNode oneHit = null;
JsonNode dataObj = null;
int idx = 0;
Data data = null;
if (hits != null)
{
hits = hits.get("hit");
if (hits != null)
{
while ((oneHit = hits.get(idx)) != null)
{
dataObj = oneHit.get("data");
System.out.println("Data[" + idx + "]: " + dataObj);
idx++;
}
}
}
Output:
Data[0]: {"id":"tt1185834","data":{"actor":["Abercrombie, Ian","Baker, Dee","Burton, Corey"],"title":["Star Wars: The Clone Wars"]}}
Data[1]: {"id":"tt0121766","data":{"actor":["Bai, Ling","Bryant, Gene","Castle-Hughes, Keisha"],"title":["Star Wars: Episode III - Revenge of the Sith"]}}
You can still use your Data class implementation, but I believe this will require getting the String representing each data - as above relying on toString, or using JsonNode.getText() - and re-parsing it using the ObjectMapper:
mapper.readValue(dataArray, Data.class));
The alternative is to use the Jackson Streaming Model, and intercept the nodes yourself until you see the part of the input that marks the beginning of each data element, then consume the string and call objectMapper.readValue on the contents, for each string.
Json-path could be a very good alternative for such a requirement - if you are okay with a solution other than Jackson that is: http://code.google.com/p/json-path/