JSON decode in Java - java

I get some JSON code like this:
{"1":{"id":"1","Vorname":"x","Nachname":"y","MaleFemale":0,"interests":[]},
"2":{"id":"2","Vorname":"x","Nachname":"y","MaleFemale":1,"interests":[]},
...
from my PHP script. Could you tell me how to decode this format in Java?
I only get examples where you have to have to have a format like this:
{"contacts": [{"user.id":"1","Vorname":"x","Nachname":"y","MaleFemale":1},
{"user.id":"2","Vorname":"x1","Nachname":"y2","MaleFemale":0}]}
So the difference is that in the first given code there is no "main node". In the second given code there is one ("contacts"). Do I need this node? I try so much but i do not get how to work this out.
Thank you very much.

I thinks you should use jackson mapper. here is a link:
How to convert Java object to / from JSON (Jackson)

You can do this easily with Jackson java library. Here is an example code snippet.
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import java.io.IOException;
public class Test {
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
// Reading the string to a JSON object
JsonNode jsonObject = mapper.readTree("{\"contacts\": [{\"user.id\":\"1\",\"Vorname\":\"x\",\"Nachname\":\"y\",\"MaleFemale\":1},\n" +
" {\"user.id\":\"2\",\"Vorname\":\"x1\",\"Nachname\":\"y2\",\"MaleFemale\":0}]}");
//Some basic querying
JsonNode contacts = jsonObject.get("contacts");
if (contacts.isArray()){
ArrayNode contactsArray = (ArrayNode) contacts;
for (JsonNode contact : contactsArray) {
System.out.println(contact.get("user.id"));
}
}
}
}
You can download the Jackson library from here.

Related

ElasticSearch Java API Client - Send already serialized data and avoid serialization

I have a Kafka Topic wit JSON data. Now im trying to send those JSON strings to an ES topic using the new "Java API Client" (https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/7.17/index.html), but im running into a parser exception:
co.elastic.clients.elasticsearch._types.ElasticsearchException: [es/index] failed: [mapper_parsing_exception] failed to parse
at co.elastic.clients.transport.rest_client.RestClientTransport.getHighLevelResponse(RestClientTransport.java:281)
at co.elastic.clients.transport.rest_client.RestClientTransport.performRequest(RestClientTransport.java:147)
at co.elastic.clients.elasticsearch.ElasticsearchClient.index(ElasticsearchClient.java:953)
This exception occurs in the last line of the following code:
final IndexRequest<String> request =
new IndexRequest.Builder<String>()
.index("myIndex")
.id(String.valueOf(UUID.randomUUID()))
.document(consumerRecord.value()) //already serialized json data
.build();
elasticsearchClient.index(request);
As far as I understand this exception occurs, because the ES client tries to serialize the data im providing, which is already serialized, resulting in a malformed JSON string.
Is there anyway to get around this and just send simple JSON strings? Also I believe this was possible with the earlier "Low Level Java Library", right? And yes, I know there are ways to allow communication between Kafka and ES without writing a Consumer.
Thanks for any hints.
If you use a JacksonJsonpMapper when creating your ElasticsearchTransport, you can use a custom PreserializedJson class to send already-serialized JSON.
ElasticsearchTransport transport = new RestClientTransport(
createLowLevelRestClient(), // supply your own!
new JacksonJsonpMapper()
);
ElasticsearchClient client = new ElasticsearchClient(transport);
IndexResponse response = client.index(indexReq -> indexReq
.index("my-index")
.id("docId")
.document(new PreserializedJson("{\"foo\":\"bar\"}"))
);
System.out.println(response);
Here is the source for PreserializedJson:
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import static java.util.Objects.requireNonNull;
#JsonSerialize(using = PreserializedJson.Serializer.class)
public class PreserializedJson {
private final String value;
public PreserializedJson(String value) {
this.value = requireNonNull(value);
}
public PreserializedJson(byte[] value) {
this(new String(value, StandardCharsets.UTF_8));
}
public static class Serializer extends StdSerializer<PreserializedJson> {
public Serializer() {
super(PreserializedJson.class);
}
#Override
public void serialize(PreserializedJson value, JsonGenerator gen, SerializerProvider provider) throws IOException {
gen.writeRaw(value.value);
}
}
}
I solved the problem by substituting "Java API Client" (https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/current/introduction.html) with "Java Low Level Rest Client" (https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/current/java-rest-low.html).
This Library allows sending of arbitrary JSON-Strings to ES:
final Request request = new Request("POST", "/twitter/_doc");
request.setJsonEntity(record.value());
restClient.performRequest(request);
With the new API Client, you can natively insert raw json into it.
As specified here : Using raw json data
IndexRequest<JsonData> request = IndexRequest.of(i -> i
.index("logs")
.withJson(input)
);

Read JSON file with JSONParser not available in the jarfile

I am trying to read a json file and convert it to the jsonObject and when I searched on how to do it, I came across the method to user
JSONParser parser= new JSONParse();
But the version of org.json I am using in the code is "20180803". It does not contain JSONParser. Has it been removed from the org.json package? If so what is the new class or method that I could use to read a json file and convert it to a json object.
My dependency is given below :
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20180813</version>
</dependency>
Hi you can use simple JSON. You just need to add in your pom.xml file:
<dependency>
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId>
</dependency>
Sample code
public static JSONObject convertJsonStingToJson(String jsonString) {
JSONParser parser = new JSONParser();
return json = (JSONObject) parser.parse(jsonString);
}
org.json library has very simple API which does not have JSONParser but has JSONTokener. We can construct JSONObject or JSONArray directly from String:
import org.json.JSONArray;
import org.json.JSONObject;
public class JsonApp {
public static void main(String[] args) {
// JSON Object
String object = "{\"p1\":\"v1\", \"p2\":2}";
JSONObject jsonObject = new JSONObject(object);
System.out.println(jsonObject);
// JSON Array
String array = "[{\"p1\":\"v1\", \"p2\":2}]";
JSONArray jsonArray = new JSONArray(array);
System.out.println(jsonArray);
}
}
Above code prints:
{"p1":"v1", "p2":2}
[{"p1":"v1","p2":2}]
You need to notice that it depends from JSON payload which class to use: if JSON starts from { use JSONObject, if from [ - use JSONArray. In other case JSON payload is invalid.
As it mentioned in other answers, if you can you should definitely use Jackson or Gson
Add following dependency in build file
//json processing
implementation("com.fasterxml.jackson.core:jackson-core:2.9.8")
implementation("com.fasterxml.jackson.core:jackson-annotations:2.9.8")
implementation("com.fasterxml.jackson.core:jackson-databind:2.9.8")
a.json file
{
"a": "b"
}
code:
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.FileInputStream;
import java.io.InputStream;
public class App {
public static void main(String[] args) throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
InputStream input = new FileInputStream("a.json");
JsonNode obj = objectMapper.readTree(input);
System.out.println(obj.get("a")); // "b"
}
}
The short answer to your question is: No, it was not removed, because it never existed.
I think you are mentioning a library, and trying to use another one. Anyway, if you really want to use org.json, you can find how here
JSONObject jsonObject = new JSONObject(instanceOfClass1);
String myJson = jsonObject.toString();

Parsing JSON ARRAY in Java: Java code + correct import + Url (link) to download the JAR

I need to write a code to Parsing JSON ARRAY in Java.
Please give me:
1) Java code
2) correct import of corresponding jar library
3) Url (link) to download the JAR
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
public static <T> T jsonStringToObject(String jsonString , Class<T> objectClass){
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
T t=null;
try {
t = mapper.readValue(jsonString, objectClass);
} catch (IOException e) {
e.printStackTrace();
}
return t;
}
Person person=jsonStringToObject(jsonString, Person.class);
//note person call have same property as of json
download jacson-core jar from here
http://www.java2s.com/Code/Jar/c/Downloadcomfasterxmljacksoncorejar.htm

Using builder to create nested XML

I'm using the Jackson set of classes to read in a CSV file, and convert it to xml, but need some advice on how to add a nested value.
The code I'm using is:
package reader;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import com.fasterxml.jackson.databind.MappingIterator;
import com.fasterxml.jackson.dataformat.csv.CsvMapper;
import com.fasterxml.jackson.dataformat.csv.CsvSchema;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
public class Mustang
{
public static void main(String[] args) throws Exception
{
// Define the input file
File input = new File("c:\\temp\\all_idocs.csv");
// Define the output file
File output = new File("c:\\temp\\all_idocs.xml");
System.out.println("INFO: Commencing Conversion");
List<Map<?, ?>> data = readObjectsFromCsv(input); // readObjectsFromCSV(input
// file name)
System.out.println(readObjectsFromCsv(input));
writeAsXml(data, output); // writeAsXml function, to output location
System.out.println("INFO: Conversion Complete");
}
public static List<Map<?, ?>> readObjectsFromCsv(File file)
throws IOException
{
CsvSchema schema = CsvSchema.builder()
.addColumn("A0001")
.addColumn("A0186")
.addColumn("A0187")
.addColumn("A0352")
.addColumn("A0539")
.addColumn("A0963")
.addColumn("A1046")
.addColumn("A0792")
.addColumn("A0218")
.addColumn("A0584")
.addColumn("A0016")
.addColumn("A0017")
.addColumn("A0478")
.addColumn("A0051")
.addColumn("A0052")
.addColumn("A0053")
.addColumn("A0059")
.addColumn("A0440")
.addColumn("A0054")
.addColumn("A0055")
.addColumn("A0056")
.addColumn("A0057")
.addColumn("A0058")
.addColumn("A1128")
.addColumn("A0003")
.addColumn("A0069")
.addColumn("A0070")
.addColumn("A0074")
.addColumn("A0073")
.addColumn("A0071")
.addColumn("A0110")
.addColumn("A0109")
.addColumn("A0108")
.build();
CsvMapper csvMapper = new CsvMapper();
MappingIterator<Map<?, ?>> mappingIterator = csvMapper
.reader(Map.class).with(schema).readValues(file); // Change the "with()" to pull in the schema
return mappingIterator.readAll();
}
public static void writeAsXml(List<Map<?, ?>> data, File file)
throws IOException
{
XmlMapper mapper = new XmlMapper();
mapper.writeValue(file, data);
}
}
If I run this against a CSV file, I get output similar to this:
<item>
<A0001>J1000097</A0001>
<A0186>5028197000004</A0186>
<A0187>1</A0187>
<A0352></A0352>
<A0539>00</A0539>
<A0963>20050209</A0963>
</item>
I want to see if it's possible to indent/nest some of these attributes, to produce something like this:
<item>
<A0001>J1000097</A0001>
<A0186>5028197000004</A0186>
<A0187>
<A0352>12</A0352>
<A0539>00</A0539>
</A0187>
<A0963>20050209</A0963>
</item>
I'm assuming I must have to do something within the builder section of the code, but as I'm new to using it, I can't fathom out how.
In this case you may want to process Map after reading it from CSV, but before writing it as XML. You can then add a wrapper around values you want to group. That is, something like:
Map<?,?> value = ... ; // individual row
Map<String,Object> wrapped = new LinkedHashMap<>();
wrapped.put("A0352", value.remove("A0352"));
wrapped.put("A0539", value.remove("A0539"));
value.put("A0187", wrapped);
another possibility would be to use value conversion between Map, and POJO type that uses #JsonUnwrapped to handle grouping.
Conversion itself may be done using:
MyPOJO value = mapper.convertValue(map, MyPOJO.class); // and/or reverse
but this approach may become more complicated.

Reading multiple JSON Objects from a single file into Java with Jackson

So I've done my best to research similar issues like this, but I'm fairly new to Java and JSON, so I apologize if this is redundant. I'm working on a simple text based RPG for my Java class this semester, and I want to store character information and location information in either XML or JSON. I've given both a try, and seem to be getting farther with JSON and Jackson. I've written some tester code to try this out before implementing in my game, but basically I want each game "location" to have an integer ID#, some string information, and a list of exitNodes (which will eventually correspond to other locations in the game). Here is an example of my JSON:
{
"1":{
"enterInfo":"Test Location Information",
"exitNodes":[2,3]
},
"2":{
"enterInfo":"More Test Location Info",
"exitNodes":[4,5]
},
"3":{
"enterInfo":"More Test Location Info",
"exitNodes":[6,7]
}
}
I'm guessing I could organize my JSON a bit better, but ideally I want to be able to grab an object by it's number, and get the "enterInfo" and "exitNodes" back. I've spent hours trying different things without success, but the best I can do is grab the whole JSON document as a JsonNode which just gives me the entire structure, but not an individual object.
Here is a test class (minus constructor/getters/setters/methods) I'm trying to get the JSON into:
public class ObjectTest{
int id;
String enterInfo;
int[] exitNodes;
}
And here is what I have working so far, I realize that I'm not even close to achieving my goal here, but I'm out of ideas and the documentation is starting to get confusing, so I've removed my attempts to isolate one of the objects in the JSON file and instantiate an "ObjectTest" object:
package jacksontester;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
import java.io.IOException;
public class JackSONTester {
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
JsonNode localeTemp = mapper.readTree(new File("src/jacksontester/TestMeJSON.json"));
System.out.println(localeTemp);
}
}
Not that it really matters, but here is what prints out:
{"1":{"enterInfo":"Test Location Information","exitNodes":[2,3]},"2":{"enterInfo":"More Test Location Info","exitNodes":[4,5]},"3":{"enterInfo":"More Test Location Info","exitNodes":[6,7]}}
What I want to achieve is being able to create an "ObjectTest" object with the values from my JSON. Again, sorry if this is a duplicate, I've read through numerous posts already, but I'm new here...
EDIT: I'm realizing now that my JSON file should probably be organized more like this:
{"locations":[
{ "id":0,
"enterInfo":"Test Location Information",
"exitNodes":[1,2]
},
{ "id":1,
"enterInfo":"More Test Location Info",
"exitNodes":[2,3]
},
{ "id":2,
"enterInfo":"More Test Location Info",
"exitNodes":[4,5]
}
]
}
I would need to then create a list of objects defined by the JSON?
This should solve it for you:
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.type.TypeReference;
import java.io.File;
import java.io.IOException;
import java.util.List;
public class JacksonTester {
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
List<ObjectTest> myObjects = mapper.readValue(jsonFile(), new TypeReference<List<ObjectTest>>(){});
System.out.println(myObjects);
}
private static File jsonFile() {
return new File("src/main/resources/test.json");
}
}
Using this as JSON:
[{
"id":0,
"enterInfo":"Test Location Information",
"exitNodes":[1,2]
},
{ "id":0,
"enterInfo":"Test Location Information",
"exitNodes":[1,2]
}]
Reference
EDIT
Forgot to say that the fields need to have setters or to be public

Categories

Resources