I am trying find some vin data from http://developer.edmunds.com/ using https://api.edmunds.com/v1/api/toolsrepository/vindecoder?vin=1GCEC19C17Z275639&fmt=json&api_key=my_api_key.... I am getting a full json data. I am using simplest way to read json from a URL in java JSONParser and my return data looks like http://pastebin.com/30jXEGvN this.
What is the best way to print all keys and its values from a jsonobject ?
I tried
Iterator<?> keys = object.keys();
while( keys.hasNext() ){
String key = (String)keys.next();
try {
if( object.get(key) instanceof JSONObject ){
detailsTextOut.append(key);
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
But its not working for me :( , any clues ?
Using Jackson ObjectMapper:
String s = "replace_with_your_json_string";
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> values = (Map<String, Object>) mapper.readValue(s, Map.class);
iterate(values, "");
private void iterate(Map<String, Object> map, String indent) {
for(Map.Entry<String, Object> o : map.entrySet()) {
System.out.println(indent + o.getKey());
if(o.getValue() instanceof Map) {
iterate((Map<String, Object>) o.getValue(), indent + "\t");
}
if(o.getValue() instanceof List) {
iterate((List<Object>) o.getValue(), indent + "\t");
}
else if(o.getValue() instanceof String) {
System.out.println(indent + "\t" + o.getValue());
}
else if(o.getValue() instanceof Number) {
System.out.println(indent + "\t" + o.getValue());
}
}
}
private void iterate(List<Object> list, String indent) {
for(Object o : list) {
if(o instanceof Map) {
iterate((Map<String, Object>) o, indent + "\t");
}
if(o instanceof List) {
iterate((List<Object>) o, indent + "\t");
}
else if(o instanceof String) {
System.out.println(indent + "\t" + o);
}
else if(o instanceof Number) {
System.out.println(indent + "\t" + o);
}
}
}
Use the method getNames() to get all the keys (field name) of JSON object.
JSONObject api
String[] keys = JSONObject.getNames(jsonObject);
for (String key : keys) {
//then get value by key (field name)
Object obj = jsonObject.get(key);
System.out.println(key + "-" + obj.toString());
}
Related
I am able to update the value of jsonObject by using key name , here the method which I am using
private static JSONObject setValue(JSONObject json, String key, String newValue) throws JSONException {
Iterator<?> keys = json.keys();
while (keys.hasNext()) {
String k = (String) keys.next();
if (key.equals(k)) {
json.put(key, newValue);
}
Object value = json.opt(k);
if (value instanceof JSONObject) {
setValue((JSONObject) value, key, newValue);
}
}
return json;
}
But this is not working in case of JSONArray object , I tried surfing , tried some method but not able to get desire output , an sample request payload:
{
"sactions": [
{
"fund": "REAL",
"amount": {
"value": 130.24,
"curr": "RMB"
},
"type": "TD",
"desc": "TD",
"code": "PROMO",
"id": "deaedd69e3-6707-4b27-940a-39c3b64abdc7"
}
]
}
Looking an recursive method to update value for any given key.
This is what I tried , but did not work
public static JSONObject setProperty(JSONObject js1, String keys, String valueNew) throws JSONException {
String[] keyMain = keys.split("\\.");
for (String keym : keyMain) {
Iterator<?> iterator = js1.keys();
String key = null;
while (iterator.hasNext()) {
key = (String) iterator.next();
if ((js1.optJSONArray(key) == null) && (js1.optJSONObject(key) == null)) {
if ((key.equals(keym))) {
js1.put(key, valueNew);
return js1;
}
}
if (js1.optJSONObject(key) != null) {
if ((key.equals(keym))) {
js1 = js1.getJSONObject(key);
break;
}
}
if (js1.optJSONArray(key) != null) {
JSONArray jArray = js1.getJSONArray(key);
for (int i = 0; i < jArray.length(); i++) {
js1 = jArray.getJSONObject(i);
}
break;
}
}
}
return js1;
}
This is how I am using the method (Ceating request body using lombok and jakson)
ObjectMapper mapper = new ObjectMapper();
String.valueOf(setValue(new JSONObject(mapper.writeValueAsString(transferFund())),
field, " "))
Thanks in advance
You can utilize JsonPath jayway to save your time.
For example:
String jsonInput = "{\n" +
" \"sactions\": [\n" +
" {\n" +
" \"fund\": \"REAL\",\n" +
" \"amount\": {\n" +
" \"value\": 130.24,\n" +
" \"curr\": \"RMB\"\n" +
" },\n" +
" \"type\": \"TD\",\n" +
" \"desc\": \"TD\",\n" +
" \"code\": \"PROMO\",\n" +
" \"id\": \"deaedd69e3-6707-4b27-940a-39c3b64abdc7\"\n" +
" }\n" +
" ]\n" +
"}";
String newJson = JsonPath.parse(jsonInput).set("$..id", "test").jsonString();
System.out.println(newJson);
Say the input is:
[{keyname: firstname, path:person.name.firstname,type:string},
{keyname:age, path:person.age,type:number}]
Then jsonschema should be generated from the json
{ person:{
name:{ firstname: guest },
age: 6
}}
I need the json schema
#Component
public class SchemaUtil {
#Autowired
ObjectMapper mapper;
//Converts path of type -> $.eventMessage.phoneNumbers[:1].type to -> /eventMessage/phoneNumbers/0/type
public String pathConverter(String path) {
String newString=path.replace("$", "").replace(".", "/").replaceAll("\\[(.*?)\\]","/0");
return newString;
}
public String getSchema(List<SchemaPOJO> schemaList)
{
ObjectNode rootNode = mapper.createObjectNode();
StringBuilder output = new StringBuilder();
try
{
for(SchemaPOJO schema: schemaList)
{
String path = pathConverter(schema.getPath());
create(rootNode,path,schema.getDataType());
if(path.contains("/0/"))
{
int index1=path.indexOf("/0/");
while(index1 != -1)
{
String temp = path.substring(0,index1+1)+'1'+path.substring(index1+2);
create(rootNode,temp,schema.getDataType());
index1=path.indexOf("/0/",index1+1);
}
}
}
output.append("{\"$schema\":\"http://json-schema.org/draft-04/schema#\","
+ "\"type\": \"object\", \"properties\": {");
output.append(makeSchema(mapper.writeValueAsString(rootNode),null));
}
catch(Exception e)
{
return null;
}
List<String> keys = new ArrayList<>();
Iterator<String> iterator = rootNode.fieldNames();
iterator.forEachRemaining(e -> keys.add(e));
String inParams = String.join(",", keys.stream().map(key1 -> "\""+key1+"\"").collect(Collectors.toList()));
output.append(",\"required\":["+inParams+"]");
output.append("}");
return output.toString();
}
//Creates dummy values in json
private void create(ObjectNode rootNode, String path,String dataType)
{
switch(dataType)
{
case "string":createJson(rootNode, JsonPointer.compile(path), new TextNode("stringdummytext"));break;
case "integer":createJson(rootNode, JsonPointer.compile(path), new IntNode(65734));break;
case "float":createJson(rootNode, JsonPointer.compile(path), new FloatNode(124));break;
case "boolean":createJson(rootNode, JsonPointer.compile(path),BooleanNode.getFalse());break;
default:createJson(rootNode, JsonPointer.compile(path), new TextNode("stringdummytext"));break;
}
}
//Creates dummy json
private void createJson(ObjectNode node, JsonPointer pointer, JsonNode value) {
JsonPointer parentPointer = pointer.head();
JsonNode parentNode = node.at(parentPointer);
String fieldName = pointer.last().toString().substring(1);
if (parentNode.isMissingNode() || parentNode.isNull()) {
parentNode = StringUtils.isNumeric(fieldName) ? mapper.createArrayNode() : mapper.createObjectNode();
createJson(node,parentPointer, parentNode);
}
if (parentNode.isArray()) {
ArrayNode arrayNode = (ArrayNode) parentNode;
int index = Integer.parseInt(fieldName);
for (int i = arrayNode.size(); i <= index; i++) {
arrayNode.addNull();
}
arrayNode.set(index, value);
} else if (parentNode.isObject()) {
((ObjectNode) parentNode).set(fieldName, value);
} else {
throw new IllegalArgumentException("`" + fieldName + "` can't be set for parent node `"
+ parentPointer + "` because parent is not a container but " + parentNode.getNodeType().name());
}
}
//Makes schema from dummy json
private String makeSchema(String json,JsonNodeType jsonNodeType) throws IOException
{
JsonNode jsonNode = mapper.readTree(json);
StringBuilder output = new StringBuilder();
for (Iterator<String> iterator = jsonNode.fieldNames(); iterator.hasNext();)
{
String fieldName = iterator.next();
JsonNodeType nodeType;
nodeType = jsonNode.get(fieldName).getNodeType();
output.append(convertNodeToStringSchemaNode(jsonNode, nodeType, fieldName));
output.append(",");
}
if( (jsonNodeType==null) || (jsonNodeType.name().equals("ARRAY")) || (jsonNodeType.name().equals("OBJECT")))
output.deleteCharAt(output.length()-1);
else if(jsonNode.getNodeType().name().equals("STRING"))
output.append("string\"");
else if(jsonNode.getNodeType().name().equals("NUMBER"))
output.append("integer\"");
output.append("}");
return output.toString();
}
//Util Method to create json schema
private String convertNodeToStringSchemaNode(JsonNode jsonNode, JsonNodeType nodeType, String key) throws IOException
{
StringBuilder result = new StringBuilder("\"" + key + "\": { \"type\": \"");
JsonNode node = null;
switch (nodeType) {
case ARRAY :
node = jsonNode.get(key).get(0);
result.append("array\", \"items\": [{ \"type\":\"");
if(node.getNodeType().name().equals("OBJECT"))
result.append("object\", \"properties\": { ");
result.append(makeSchema(node.toString(), node.getNodeType()));
if(node.getNodeType().name().equals("OBJECT"))
{
List<String> keys = new ArrayList<>();
Iterator<String> iterator = node.fieldNames();
iterator.forEachRemaining(e -> keys.add(e));
String inParams = String.join(",", keys.stream().map(key1 -> "\""+key1+"\"").collect(Collectors.toList()));
result.append(",\"required\":["+inParams+"]");
result.append("}");
}
result.append("]}");
break;
case BOOLEAN:
result.append("boolean\" }");
break;
case NUMBER:
result.append("integer\" }");
break;
case OBJECT:
node = jsonNode.get(key);
result.append("object\", \"properties\": {");
result.append(makeSchema(node.toString(), JsonNodeType.OBJECT));
List<String> keys = new ArrayList<>();
Iterator<String> iterator = node.fieldNames();
iterator.forEachRemaining(e -> keys.add(e));
String inParams = String.join(",", keys.stream().map(key1 -> "\""+key1+"\"").collect(Collectors.toList()));
result.append(",\"required\":["+inParams+"]");
result.append("}");
break;
case STRING:
result.append("string\" }");
break;
default:
result.append("string\" }");
}
return result.toString();
}
}
I am working over JsonNode and trying to get relativePath and add as attribute .
public static void iterateOver(JsonNode masterJSON) {
Iterator<Entry<String, JsonNode>> nodes = masterJSON.fields();
while (nodes.hasNext()) {
Map.Entry<String, JsonNode> entry = (Map.Entry<String, JsonNode>) nodes.next();
JsonNode value = entry.getValue();
if(value.has("current") && value.has("older")) {
System.out.println("key --> " + entry.getKey() + " value-->" + value);
String relativePath = "";// ? how do get relative path e.g /obj/empdetails/data[0]/address;
((ObjectNode)entry.getValue()).put("relativePath", relativePath);
}
if(value.isArray()) {
for (int i = 0; i < value.size(); i++) {
iterateOver(value.get(i));
}
}else if (value.isObject()) {
iterateOver(value);
}
}
}
i want to have relativePath in such a way that at i can get the exact object as node.at(relativePath)
We are doing some integration towards a quite inconsistent (Zurmo-)REST API. The API only accepts urlencoded strings as its payload in the http posts, but it answers with JSON.
So as the documentation was very unclear on this we naturally thought we could post JSON to it, but this was not the case.
So now we have all our code generating JSON when we need to send it as x-www-form-urlencoded, is there any java library that can do a conversion from JSON to an urlencoded string?
We are currently using the org.json lib, but we can change it if there would be a need for it.
Example:
This JSON string:
{"data":{"description":"test","occurredOnDateTime":"2013-10-24 01:44:50"}}
Should be converted into this:
data%5Bdescription%5D=test&data%5BoccurredOnDateTime%5D=2013-10-24+01%3A44%3A50
Java code:
We translated rasmushaglunds javascript code to java and wrapped it, here is the result if anybody else stumbles upon this problem.
public static String jsonToURLEncoding(JSONObject json) {
String output = "";
String[] keys = JSONObject.getNames(json);
for (String currKey : keys)
output += jsonToURLEncodingAux(json.get(currKey), currKey);
return output.substring(0, output.length()-1);
}
private static String jsonToURLEncodingAux(Object json, String prefix) {
String output = "";
if (json instanceof JSONObject) {
JSONObject obj = (JSONObject)json;
String[] keys = JSONObject.getNames(obj);
for (String currKey : keys) {
String subPrefix = prefix + "[" + currKey + "]";
output += jsonToURLEncodingAux(obj.get(currKey), subPrefix);
}
} else if (json instanceof JSONArray) {
JSONArray jsonArr = (JSONArray) json;
int arrLen = jsonArr.length();
for (int i = 0; i < arrLen; i++) {
String subPrefix = prefix + "[" + i + "]";
Object child = jsonArr.get(i);
output += jsonToURLEncodingAux(child, subPrefix);
}
} else {
output = prefix + "=" + json.toString() + "&";
}
return output;
}
public static String objectToUrlEncodedString(Object object, Gson gson) {
return jsonToUrlEncodedString((JsonObject) new JsonParser().parse(gson.toJson(object)));
}
private static String jsonToUrlEncodedString(JsonObject jsonObject) {
return jsonToUrlEncodedString(jsonObject, "");
}
private static String jsonToUrlEncodedString(JsonObject jsonObject, String prefix) {
String urlString = "";
for (Map.Entry<String, JsonElement> item : jsonObject.entrySet()) {
if (item.getValue() != null && item.getValue().isJsonObject()) {
urlString += jsonToUrlEncodedString(
item.getValue().getAsJsonObject(),
prefix.isEmpty() ? item.getKey() : prefix + "[" + item.getKey() + "]"
);
} else {
urlString += prefix.isEmpty() ?
item.getKey() + "=" + item.getValue().getAsString() + "&" :
prefix + "[" + item.getKey() + "]=" + item.getValue().getAsString() + "&";
}
}
return urlString;
}
There is an easier way now, and that is to use the URLEncoder.encode method.
Import the URLEncoder package:
import java.net.URLEncoder;
and then:
URLEncoder.encode(objectMapper.writeValueAsString(<yourClass>), StandardCharsets.UTF_8.toString());
You can test your result here:
https://onlinejsontools.com/url-decode-json
As noted below, it's not a Java library but you should be able to translate it :)
Here's how you could do it in javascript:
var jsonArrayToUrl = function (obj, prefix) {
var urlString = "";
for (var key in obj) {
if (obj[key] !== null && typeof obj[key] == "object") {
prefix += "[" + key + "]";
urlString += jsonArrayToUrl(obj[key], prefix);
}else{
urlString += prefix + "[" + key + "]=" + obj[key] + "&";
}
}
return encodeURIComponent(urlString);
};
Then call it with
jsonArrayToUrl(test["data"], "data");
By the example string you gave above it returns
"data%5Bdescription%5D%3Dtest%26data%5BoccurredOnDateTime%5D%3D2013-10-24%2001%3A44%3A50%26"
It should work recursively on nested arrays. You might also consider writing a wrapper for the function so that you only need one argument.
i was wondering whether it is possible to find an object using an example object like you can in hibernate with:
Cat cat = new Cat();
cat.Sex = 'F';
cat.Color = Color.Black;
List results = session.CreateCriteria(typeof(Cat)).Add( Example.Create(cat)).List();
I know i can find by primary key, just not looking forward to writing a million lines of findByX, findByY etc etc.
thanks.
Nico
It seems as if the Criteria API is being considered for the next JPA release. There is some discussion about it here.
It would seem that at the moment if you want the Query by Example and Criteria features then you will have to use Hibernate.
so since it's not available in the current JPA API, the only way i can see how to implement it would be by using this:
public <T> List<T> findByAttribute(T object) {
List<T> found = new ArrayList<T>();
Map m = null;
try {
m = BeanUtils.describe(object);
} catch (Exception ex) {
return null;
}
String query = "select c from " + object.getClass().getSimpleName() + " c where ";
if (m != null) {
for (Object key : m.keySet()) {
if (!key.equals("class")) {
Object value = m.get(key);
if (value != null) {
try {
ConvertUtils.convert(m.get(key), PropertyUtils.getPropertyType(object, key.toString()));
query += " c." + key + " = :" + key + " and";
} catch (Exception ex) {
// the reason for this noncy try catch is so that you don't add parameters that are not primitives
}
}
}
}
query = query.substring(0, query.lastIndexOf("and"));
Query q = getEntityManager().createQuery(query);
for (Object key : m.keySet()) {
if (!key.equals("class")) {
if (m.get(key) != null) {
try {
Object o = ConvertUtils.convert(m.get(key), PropertyUtils.getPropertyType(object, key.toString()));
q.setParameter(key.toString(), o);
} catch (Exception ex) {
System.out.println("what we have here is a failure to communicate");
System.out.println("only primitive types allowed");
}
}
}
}
List resultList = q.getResultList();
if (resultList != null) {
found.addAll(resultList);
}
}
return found;
}
but this will only work for primitive types i think. I guess it's something.
Thanks anyway
N