i meet a problem. the org.Json lib's JSONObject do not have a equals method. but it have a toString method. I want to "abc".equals(JsonObject.toStirng()). here is the problem.
toStirng() string is not sorted. for exmple {"aa":"11","bb":"22"}, maybe, toStirng is this :
{"bb":"22","aa":"11"}, the String not equals, but json object actually equals. I decomplie the
org.json.JSONObject:
private Map map;
public JSONObject()
{
map = new HashMap();
}
i do not have the source code, i want to use asm.lib to modify the class.
so, i want to change one places , one is :
public JSONObject()
{
map = new HashMap(); -->map = new LinkedHashMap();
}
so, the string generated from toString() will be sorted, that is what i wanted.
I do know how to add a field, but i do not know how to Modify and delete a filed or a
method.
Brothers or Sisters is your time, thanks :-)
The json.org Java source is available there: https://github.com/douglascrockford/JSON-java. It is opensource but no license is specified.
You can then modify the source code.
Related
I am getting a list of objects from 3rd party but it will always contain one object only. So at my end in target I have created it as an object rather than list. That object contains multiple lists inside it just like source object.
This is how I am trying to map a list to an object. ChargeTransaction contain orderInvoice as an object and not a list. For list which are inside ChargeTransaction I have created separate mappers. I dont want to write java code in #afterMapping because then how nested lists will be mapped. The nested lists are of type in both the objects.
#Mapping(target = "orderInvoice", source = "basePaymentRequest.invoice.eventPayload.orderInvoices")
ChargeTransaction createInvoiceCTMapper(PaymentTriggerBaseModel basePaymentRequest, ChargeType chargeType);
Error
java: Can't map property "List<OrderInvoice> basePaymentRequest.invoice.eventPayload.orderInvoices" to "OrderInvoice orderInvoice". Consider to declare/implement a mapping method: "OrderInvoice map(List<OrderInvoice> value)".
I tried
#Mapping(target = "orderInvoice", expression= "java(basePaymentRequest.invoice.eventPayload.orderInvoices.get(0))")
But it gives error in Impl class
chargeTransaction.setOrderInvoice( basePaymentRequest.invoice.eventPayload.orderInvoices.get(0) );
java: incompatible types: com.sams.oms.ng.common.models.payment.request.OrderInvoice cannot be converted to com.sams.oms.ng.common.models.payment.cosmos.OrderInvoice
IMHO the best way to solve this problem is to use a #Named paired with #Mapping#qualifiedByName
#Mapper
class Mapper {
#Mapping(target = "orderInvoice", source ="basePaymentRequest.invoice.eventPayload.orderInvoices", qualifiedByName="firstElement")
ChargeTransaction createInvoiceCTMapper(PaymentTriggerBaseModel basePaymentRequest, ChargeType chargeType);
#Named("firstElement")
OrderInvoice map(List<OrderInvoice> value) {
if(value == null) return null;
if(value.isEmpty()) return null;
return map(value.get(0));
}
abstract com.sams.oms.ng.common.models.payment.request.OrderInvoice map(com.sams.oms.ng.common.models.payment.cosmos.OrderInvoice invoice);
}
In this way you are instructed MapStruct to use map(List<>) to convert invoices to a single OrderInvoice and abstract map(OrderInvoice) to let MapStruct autogenerate mapping code.
Code in untested because I haven't limited spare time today,but I hope my example may be useful;if anything is wrong feel free to comment and I will correct code asap.
I have JSONObject instance which contains some property,
{
"name":"testName",
"age":"23"
}
i use the following assert, but it fails. Is this correct approach to test JSON in assertj.
assertThat(jsonObject).hasFieldOrProperty("name");
If you want to do any serious assertions on JSON object, I would recommend JsonUnit https://github.com/lukas-krecan/JsonUnit
I think it has to do with the fact the JSONObject is like a map which has key-value pairs, while AssertJ expects Java bean-style objects to check if a property exists. I understood this from the document at https://joel-costigliola.github.io/assertj/core/api/org/assertj/core/api/AbstractObjectAssert.html#hasFieldOrProperty(java.lang.String). Hope I am looking at the right place.
I mean to say that a map or JSONObject doesn't have fields declared in it for AssertJ to look for.
You may use JSONObject.has( String key ) instead, I think.
If you use SpringBoot you can use the custom impl. for Assertj
private final BasicJsonTester json = new BasicJsonTester(getClass());
#Test
void testIfHasPropertyName() {
final JSONObject jsonObject = new JSONObject("{\n" +
"\"name\":\"testName\",\n" +
"\"age\":\"23\"\n" +
"}");
assertThat(json.from(jsonObject.toString())).hasJsonPath( "$.name");
}
Fist, you need to traverse the keysets (nodes) using the map class, then verify if the keyset contains the particular node you are looking for.
Map<String, Object> read = JsonPath.read(JSONObject, "$");
assertThat(read.keySet()).contains("name");
I am trying call a REST service and using gson I am getting the following json for the following java pojo.
pojo
public class AlphaParameters {
private int one;
private int two;
private int three;
//getter setters
//constructors
}
Json
{"one":4,
"two":5,
"three":10
}
I am using the following code
Gson gson = new Gson()
AlphaParameters alphaParameters = new AlphaParameters(one,two,three);
gson.toJson(alphaParameters );
Earlier this code used to work, but now seems the server side which is on .net changed their implementation and now they are expecting the json in the following format. Everything is same but seems now they want the toplevel variable name in the json.
{"alphaParameters":
{"one":4,
"two":5,
"three":10
}
}
Question : Is there a specific api of Gson which I can use to generate the above json without refactoring my code ?
Or writing a wrapper class to include alphaParameters will be a better approach .
( I will have to write a lot of boilerplate code for latter ).
Thanks for your help.
I don't think Gson itself allows this kind of serialization but there is a number of ways you could tackle this problem without creating wrapper classes.
In my comment, I suggested putting the object in a map but that's a bit strange and you can do it so it looks more obvious in the code and probably performs better.
public Gson wrapJson(Object objectToSerialize) {
Gson gson = new Gson();
JsonObject result = new JsonObject();
//Obtain a serialized version of your object
JsonElement jsonElement = gson.toJsonTree(objectToSerialize);
result.add(objectToSerialize.getClass().getSimpleName(), jsonElement);
return result;
}
Then you can use it like this:
AlphaParameters alphaParameters = new AlphaParameters(one,two,three);
wrapJson(alphaParameters);
This allows you to use one pretty universal method in every case like this without writing boilerplate classes.
I used the class name to generate the key but feel free to modify this as it suits you. You could pass the key name as a parameter to make this wrapper utility more flexible.
I have the following type of JSON I want to send to Java (I'm using Jersey and the default JSON Parser it comes with)
{ "something" : "1", "someOtherThing" : "2" , ... }
But instead of creating an Object with all these properties in Java, I would like to have a Single HashMap (or whatever) that will allow me to still have access to the Key and the Value
Is such a thing possible?
I don't really have any code that does the transformation, I use Jersey like this
#POST
#Path("/purchase")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public StatusResult purchase(UserPurchaseRequest upr) {
}
If i put properties something and someOtherThing as Strings in my UserPurchaseRequest object, everything will come in fine, but I want to have everything in one structure (because I don't know how many values I will get, and I need their names as well)
Yes, it is possible. But still, it depends on what JSON java API you are using. For example using Jackson JSON you can create HashMap json string like this
ObjectMapper obj = new ObjectMapper();
String json = pbj.writeValue(<HashMap object>);
or vice-versa
HashMap obj = obj.readValue(json, HashMap.class);
Note - org.codehaus.jackson.map.ObjectMapper
You just need to add a Property to your Object like this
private HashMap<String,String> purchaseValues;
Jersey takes care of the rest, for some reason while you are debugging, most of the entries appear as null in the HashMap
Converting JSON to Java
The above question is with reference to what has been described on the above thread. There are so many API(s) which provide the flexibility to return responses either in XML or JSON. **I would like to know if there is a way to automatically construct the java bean corresponding to a JSON response. **
lets say you get an object like
[
{
"name":"Java 6 Greatest Hits",
"Author":"Jim Bob Jones",
"price":10.25
},
{
"name":"How to raise a goat",
"Author":"Sir Paxton",
"price":55.97
},
{
"name":"Snow - It is cold",
"Author":"Dr. White",
"price":9.99
}
]
And you want a class like
public class Book{
private String author;
private String name;
private Number price
}
with getters and setters
One option is to use a service like JSONGen, which will create that class. You need to use it first, and include the generated code in your project.
Another option could be dynamically generate the class using javassist or CGLib, but that class would be useless unless you use reflection to access its members, so even if it would be a class, it will behave like a really annoying Map. In no way will be better that simple using JSONObject
seems a simple Message Type Entity not meet you requirement ?
if you want convert a json to an existed and known java bean class,
many lib can do so, like
http://json-lib.sourceforge.net/apidocs/net/sf/json/class-use/JSONObject.html
JSONObject.toBean(JSONObject jsonObject, Class beanClass)
Creates a bean from a JSONObject, with a specific target class.
btw, if you are communicating with restful webservice, org.springframework.web.client.RestTemplate will help you get direct bean result
insteadof json.
if class does not exists, you need program with java reflect mechanism.
try use CGLIB ,http://cglib.sourceforge.net/, dynamic create some class like BeanMap. i wrote a simple sample,
but be ware, opearting class byte is hard and you may meet strange trouble with JVM . Strongly not encourage to do so.
public static BeanMap generateBean(JSONObject json) {
BeanGenerator generator = new BeanGenerator();
Iterator keys = json.keys();
while (keys.hasNext()) {
Object key = keys.next();
Object value = json.get(key);
Class keyClass = guessValueClass(value);
generator.addProperty(key.toString(), keyClass);
}
Object result = generator.create();
BeanMap bean = BeanMap.create(result);
keys = json.keys();
while (keys.hasNext()) {
Object key = keys.next();
Object value = json.get(key);
bean.put(key, value);
}
return bean;
}
/**
* TODO fix guess
*/
static Class guessValueClass(Object value) {
try {
Integer.parseInt(value.toString());
return Integer.class;
} catch (NumberFormatException e1) {
}
try {
Double.parseDouble(value.toString());
return Double.class;
} catch (NumberFormatException e1) {
}
return String.class;
}
I believe the main issue here is that the JSON response lacks type information and last time I checked :-) in Java you need to declare the type of a class property. So some heuristics will be needed to infer the type form the value in the JSON response.
For a related question here in SO have a look at: Generate Java class from JSON?
Yes check out http://flexjson.sourceforge.net
If you're wanting to generate Java classes from JSON, perhaps you could try Jackson. It provides a lot of JSON-related functionality, including the ability to generate bytecode from arbitrary JSON. See this blog post for details.
If you're using Jackson (the most popular library there), try
https://bitbucket.org/astav/jsontojava/wiki/Home
Its open source and anyone should be able to contribute.
Summary
A JsonToJava source class file generator that deduces the schema based on supplied sample json data and generates the necessary java data structures.
It encourages teams to think in Json first, before writing actual code.
Features
Can generate classes for an arbitrarily complex hierarchy (recursively)
Can read your existing Java classes and if it can deserialize into those structures, will do so
Will prompt for user input when ambiguous cases exist