I have a json api response that is structured similar to a csv file
{
"headers": ["a", "b", "c"],
"row1": [1, 2, 3],
"row2": [4, 5, 6]
}
I need to get a POJO for each row in that json object
Ideally I'd like to declare it like
class Row {
#SerializedName("a")
Integer a;
#SerializedName("b")
Integer b;
#SerializedName("c")
Integer c;
}
So my question is, can I write a custom deserializer so that I can do something like this? It would also be useful to serialize the other direction as well.
Gson gson = new Gson();
List<Row> rows = gson.fromJson(apiResponse, new List<Row>());
The problem not in deserialization.
My way to solve your issue.
Use defaulet deserializers for parsing.
Use mapstruct to convert parsed lists to objects
Related
I am using a PrimeFaces JSONArray object containing JSON arrays, e.g. (simplified)
[['james', 12, 2019], ['sarah', 29, 2015], ['robert', 15, 2011]]
as input to a static build method which runs over the fields of the nested arrays to construct a POJO representing their data. I implement this using static build methods within both the entity and container-of-entity classes (the latter of which simply parses the JSON and calls the former build method to construct each entity). This works fine with a crude for loop:
public static MyContainer buildContainer(JSONArray json) {
MyContainer list = new MyContainer ();
for (int i = 0; i < json.length(); i++) {
MyEntity ent = MyEntity.buildEntity(json, i);
list.add(ent);
}
return list;
}
but I would like a more elegant solution, in particular one using a functional approach (to improve my knowledge of functional Java, if for no better reason). I use Jackson to parse the JSONArray representing my complete dataset to an array of JSONArrays (i.e. a JSONArray[]). This array can then be converted to a list, which allows easier functional manipulation. Here is my initial attempt at writing down what I think that would look like, which probably shows some fundamental misunderstandings of Jackson and functional Java:
public static MyContainer buildContainer(JSONArray json) {
ObjectMapper mapper = new ObjectMapper();
try {
JSONArray[] jaArr = mapper.readValue(json.toString(), JSONArray[].class);
List<JSONArray> jaList = Arrays.asList(jaArr);
MyContainer list = (MyContainer) (List<MyEntity>) Arrays.asList(json)
.stream()
.map(MyEntity::buildEntity)
.collect(Collectors.toList());
return list;
} catch (JsonProcessingException ex) {
return null;
}
}
Netbeans does not suggest anything is wrong with this, and there are no compile-time issues. At runtime, however, I get the exception
Severe: com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of org.primefaces.json.JSONArray out of START_ARRAY token.
So, my questions are why this exception arises, when the input is of the format I have shown above, and whether there is a more elegant solution than serialising the JSONArray to a string then reading it back as a JSONArray[] – i.e. could I convert my initial JSONArray more directly to a type that allows .stream() or .forEach()?
JSONArray in version 7.0 implements Iterable so you can do something like this:
StreamSupport
.stream(iterable.spliterator(), false)
.map(MyEntity::buildEntity)
.collect(Collectors.toList());
See also:
Convert Iterable to Stream using Java 8 JDK
At the moment the Jackson parser is parsing empty objects to "{}" and empty lists to "[]". How can I get the parser to parse the empty array to null?
I know that we can write custom serializers in java. Please let me know an example to parse Object. This should be more generic to Objects
Sample Code:
class Person
{
String name;
List<Event> events;
//....getter, setter
}
person.list = new List<Event>();
persion.name = "hello";
then excepted the json would be:
{name: "hello", list : null} and not {name: "hello", list : []}
basically, if anything is empty in the Object it should be set to null
I have JSON array like this:
[{"BMW": [], "OPEL": [], "Mercedes": []}]
and I want to get
[{"Mercedes": [], "OPEL": [], "BMW": []}]
How can I make like this?
Since JSONObjects are not keeping their order in which you build them (has to do with how it's handled in memory) you should refactor the data.
[{"BMW": [], "OPEL": [], "Mercedes": []}]
to
[{"BMW":[]}, {"OPEL":[]}, {"Mercedes":[]}]
That still won't help you right away though since JSONArray in java doesn't appear to have reverse() method :(
So like I commented: build a new JSONArray in reverse order:
JSONArray newJsonArray = new JSONArray()
for (int i = jsonArray.length()-1; i>=0; i--) {
newJsonArray.put(jsonArray.get(i));
}
A small yet best solution to this is to store the JSON array in reverse order:
JSONArray array = response.getJSONArray("records");
for (int i = array.length()-1; i >= 0; i--) {
// Perform your regular JSON Parsing here
}
You dont need to edit / change your JSON
You have a JSON object, not an array. An object is comprised of key-value pairs, but these pairs are not ordered by key in any way. In fact, the order should not matter - the representation is the same.
From the ECMAScript spec, as copied here: http://interglacial.com/javascript_spec/a-4.html
4.3.3 Object An object is a member of the type Object. It is an unordered collection of properties each of which contains a primitive
value, object, or function. A function stored in a property of an
object is called a method.
I have an issue I haven't been able to find a solution to, because it's not quite straight forward I guess...
In my Java program, I receive a string like this (from an existing source, I can't change it, sadly):
["a", 1, "b", 2, ["c", "d", 3], 4]
This string is a valid JSON array (no object, so no key/value pairs!). The content of the array may be totally random (for instance, empty) but can also be multi-dimensional.
I need to find a way to read this in Java. For instance, input.get(4).get(2) should give me 3 in the above example. I don't really care if everything is casted to a string, but I need to find a way to reach the data through indices. Data may also be multiple characters, although my example shows only 1 per element.
How do I accomplish this? Thanks in advance!
Edit; I do know how many elements I expect in the root array, but there are a few dozen cases so I really don't want to program something different for each case
Pick a JSON library. Any of them.
The basic org.json:
JSONArray array = new JSONArray(yourString);
JSONArray arrayTwo = array.getJSONArray(4);
int i = arrayTwo.getInt(2);
Gson:
JsonElement element = new JsonParser().parse(json);
JsonArray array = element.getAsJsonArray();
JsonArray arrayTwo = array.get(4).getAsJsonArray();
int i = arrayTwo.get(2).getAsInt();
Etc, etc.
Using jackson 2.3.0:
import com.fasterxml.jackson.databind.*;
ObjectMapper mapper = new ObjectMapper();
JsonNode node = mapper.readTree("[\"a\", 1, \"b\", 2, [\"c\", \"d\", 3], 4]");
int i = node.path(4).path(2).intValue();
System.out.println(i);
prints
3
Javadoc for JsonNode is here.
I know php a little. and java much little.
I am creating a small application to search a text in a text area and store the result in a array.
The array in PHP will look like this.
array(
"searchedText" => "The text that is searched",
"positionsFound" => array(12,25,26,......),
"frequencies" => 23 //This is total words found divided by total words
);
But, java does not support array with multiple data types. In the above array, only the second element "positionFound" is of variable length.
Later on I need to iterate through this array and create a file including all above mentioned elements.
Please guide me
Java does support Objects. You have to define a Class like
class MyData {
String searchedText;
Set<Integer> positionsFound;
int frequencies;
}
List<MyData> myDataList = new ArrayList<MyData>();
// OR
MyData[] myDataArray = new MyData[number];
And you can use this structure to hold your data. There are other methods which are helpful such as constructors and toString() and I suggest you use your IDE to generate those.
When writing this data to a file, you might find JSon a natural format to use.
I suggest you look at GSon which is a nice JSon library.
From the GSon documentation, here is an example
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