I have a number of json objects concatenated into one string, and need to parse all of them. Simple example:
String jsonStr = "{"name":"peter","age":40}{"name":"laura","age":50}"
When using an ObjectMapper of jackson to parse this, it finds and reads the first json correctly, and drops the rest of the string.
ObjectMapper objectMapper = new ObjectMapper();
JsonNode rootNode = objectMapper.readTree(jsonStr);
System.out.println(rootNode);
Gives output {"name":"peter","age":20}
Is there any way (in Jackson or another framework) of e.g. returning the number of read characters, or the rest of the string, or an array of JsonNodes?
I found questions with the same goal in JavaScript and in Python, where it was recommended to split by }{ or regex to reformat this to a json array, but I still hope for a more elegant solution.
You don't need to modify your input as suggested by others, just use below code.
Main Method
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
JsonFactory factory = new JsonFactory(mapper);
JsonParser parser = factory.createParser(new File("config.json"));
// factory.createParser(String) and many other overload methods
// available, byte[], char[], InputStream etc.
Iterator<Person> persons = parser.readValuesAs(Person.class);
while(persons.hasNext()) {
Person p = persons.next();
System.out.printf("%s: %d%n", p.getName(), p.getAge());
}
}
Person Class
public class Person {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
config.json file
{"name":"peter","age":40}{"name":"laura","age":50}
Program Output
peter: 40
laura: 50
Library used
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.5</version>
</dependency>
In Json, an object structure starts with { and ends with }. Hence ObjectMapper thinks that there is nothing more to process as soon as it encounters }.
In Json an array is indicated with []. So if you wish to have multiple elements / objects it needs to be enclosed with [] and a comma separating individual objects
"[
{"name":"peter","age":40},
{"name":"laura","age":50}
]"
You can wrap the input with brackets [] and then replace every }{ with },{, and then finally parse the string as array:
String input = "{\"name\":\"peter\",\"age\":40}{\"name\":\"laura\",\"age\":50}"
String jsonArray = "[" + input.replace("}{", "},{") + "]";
ObjectMapper mapper = new ObjectMapper();
JsonNode parsedJsonArray = mapper.readTree(jsonArray);
you have to modify your JSON
String jsonStr = "[{\"name\":\"peter\",\"age\":40},{\"name\":\"laura\",\"age\":50}]";
There are multiple ways to convert JSON into java object.
1st Way
public JsonNode convertIntoJsonNode(String jsonStr)
{
ObjectMapper objectMapper = new ObjectMapper();
JsonNode rootNode = null;
try {
rootNode = objectMapper.readTree(jsonStr);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return rootNode;
}
2nd Ways
// check also imports
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
// User Model
class User{
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
#Override
public String toString() {
return "User [name=" + name + ", age=" + age + "]";
}
}
//Coversion Method
public List<User> convertIntoObject(String jsonStr)
{
ObjectMapper objectMapper = new ObjectMapper();
User[] myObjects = null;
try {
myObjects = objectMapper.readValue(jsonStr, User[].class);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return Arrays.asList(myObjects);
}
3rd way you can directly parse without array
public List<User> convertIntothirdway(String jsonStr)
{
ObjectMapper objectMapper = new ObjectMapper();
List<User> userList = null;
try {
userList = objectMapper.readValue(jsonStr, new TypeReference<List<User>>(){});
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return userList;
}
4th way
List<User> userList = mapper.readValue(jsonInput, mapper.getTypeFactory().constructCollectionType(List.class, User.class));
Related
I have a json a file that doesnt contain only my api i am new to json and trying to get my api parameters from the file
"operators": {
"tez" : {
"api": "www.my-tour.com/search/getResult",
"parameters": [
{
"country": "Canada",
"queryParameters": {
"priceMin": ["0"],
"priceMax":["150000"],
"currency":["5561"],
"nightsMin":[1,2,3,4,5,6,7,8,9,10,11,12,13],
"nightsMax":[1,2,3,4,5,6,7,8,9,10,11,12,13]
In my app operator is just simple the company that owns the api so i have many operators so "tez" is the name of the company and below is its api and param
#Override
public JsonObject fetchData(String url) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date());
calendar.add(Calendar.DAY_OF_MONTH, 20);
for (int i = 1; i <= 180; i++) {
String formattedDate = dateFormat.format(calendar);
url += "&after=" + formattedDate + "&before=" + formattedDate;
// how can i get the api iteratively to get all api param
JsonObject json = new JsonObject().getJsonObject("tez");
// TODO call eternal API here
JSONParser parser = new JSONParser();
JsonObject a = null;
try {
FileReader fileReader = new FileReader("\\home\\user\\MyProjects\\MicroserviceBoilerPlate\\src\\config\\local_file.json");
a = (JsonObject) parser.parse(fileReader);
} catch (Exception e1) {
e1.printStackTrace();
}
This above is what i am came up with but its not correct im not able to access the json file and how can i iterate through the parameters so i can add them to the api
www.my-tour.com/search/getResult?priceMin=0&priceMax=150000¤cy=+value &nightsMin= + value &nightsMax=+values etc
Note: This is a vertx app and i am using JsonObject and other Json specific api's
You could just make an object of the JSON properties in the file
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import java.util.List;
#JsonIgnoreProperties(ignoreUnknown = true)
public class TezModel {
public Operators operators;
public String getApi() {
return operators.tez.api;
}
public List<String> getPriceMin() {
return operators.tez.parameters.get(0).queryParameters.priceMin;
}
public List<String> getPriceMax() {
return operators.tez.parameters.get(0).queryParameters.priceMax;
}
public List<String> getCurrency() {
return operators.tez.parameters.get(0).queryParameters.currency;
}
public List<Integer> getNightsMin() {
return operators.tez.parameters.get(0).queryParameters.nightsMin;
}
public List<Integer> getNightsMax() {
return operators.tez.parameters.get(0).queryParameters.nightsMax;
}
#JsonIgnoreProperties(ignoreUnknown = true)
public static class Operators {
public Tez tez;
}
#JsonIgnoreProperties(ignoreUnknown = true)
public static class Tez {
public String api;
public List<Parameters> parameters;
}
#JsonIgnoreProperties(ignoreUnknown = true)
public static class Parameters {
public String country;
public QueryParameters queryParameters;
}
#JsonIgnoreProperties(ignoreUnknown = true)
public static class QueryParameters {
public List<String> priceMin;
public List<String> priceMax;
public List<String> currency;
public List<Integer> nightsMin;
public List<Integer> nightsMax;
}
}
And then you could add your parameters to a string using jackson databind
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
TezModel tezModel = mapper.readValue(new File("local_file.json"), TezModel.class);
String api = tezModel.getApi()+ "+priceMin="
+ tezModel.getPriceMin().get(0)
+ "&priceMax=" + tezModel.getPriceMax().get(0)
+ "¤cy=+" + tezModel.getCurrency().get(0)
+ "nightsMin=" + tezModel.getNightsMin().get(0)
+ "nightsMax=" + tezModel.getNightsMax().get(0);
System.out.println(api);
}
This Json
{
"age":"23",
"name":"srinivas",
"blog":"A",
"messages":["msg1","msg2","msg3"]
}
I want convert a json to java class like this class and class use:
public class A
{
private String name;
private String age;
private String blog;
private String[] messages;
public String getName ()
{
return name;
}
public void setName (String name)
{
this.name = name;
}
public String getAge ()
{
return age;
}
public void setAge (String age)
{
this.age = age;
}
public String getBlog ()
{
return blog;
}
public void setBlog (String blog)
{
this.blog = blog;
}
}
No. You cant have class created automatically for you from your json.
However the below thing you might be needing that's related:
You need link
Excerpt from the link, below example code:
String carJson =
"{ \"brand\" : \"Mercedes\", \"doors\" : 5," +
" \"owners\" : [\"John\", \"Jack\", \"Jill\"]," +
" \"nestedObject\" : { \"field\" : \"value\" } }";
ObjectMapper objectMapper = new ObjectMapper();
try {
JsonNode node = objectMapper.readValue(carJson, JsonNode.class);
JsonNode brandNode = node.get("brand");
String brand = brandNode.asText();
System.out.println("brand = " + brand);
JsonNode doorsNode = node.get("doors");
int doors = doorsNode.asInt();
System.out.println("doors = " + doors);
JsonNode array = node.get("owners");
JsonNode jsonNode = array.get(0);
String john = jsonNode.asText();
System.out.println("john = " + john);
JsonNode child = node.get("nestedObject");
JsonNode childField = child.get("field");
String field = childField.asText();
System.out.println("field = " + field);
} catch (IOException e) {
e.printStackTrace();
}
You technically can create a class at runtime: see How to create a class dynamically in java or Creating classes dynamically with Java. However, if your code wants to use A in some way, it needs to be available during compilation. And if your code doesn't need to use A, why create it? You could implement some interface/extend some class which is available during compilation, but in your case there is no reasonable common interface and you could only access it using reflection.
A more reasonable alternative would be to generate a class from known JSON examples (or better, from some schema description) during your build process. Again, there are many ways to do this and you should search for one which fits your needs.
I have JSON request and response, I want to print the JSONs in the log, but there are some secured fields which I want to avoid to print in the log, I am trying to mask fields keys:
example:
before masking:
{"username":"user1","password":"123456","country":"US","creditCardNumber":"1283-1238-0458-3458"}
after masking
{"username":"user1","password":"XXXXXX","country":"US","creditCardNumber":"XXXXXX"}
I am using java Gson lib, please help me to do that
EDIT
I want to pass the keys dynamically, so in function a I want to mask these fields, but in function b different fields.
I think you should exclude that fields from log. Below is a simple example using Gson and #Expose annotation.
public static void main(String[] args) throws IOException {
String json = "{\"username\":\"user1\",\"password\":\"123456\",\"country\":\"US\",\"creditCardNumber\":\"1283-1238-0458-3458\"}";
Gson gson = new Gson();
User user = gson.fromJson(json, User.class);
System.out.println(gson.toJson(user));
Gson gsonExpose = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
System.out.println(gsonExpose.toJson(user));
}
public class User {
#Expose
private String username;
private String password;
#Expose
private String country;
private String creditCardNumber;
}
Output will be:
{"username":"user1","password":"123456","country":"US","creditCardNumber":"1283-1238-0458-3458"}
{"username":"user1","country":"US"}
Another solution using Reflection:
public static void main(String[] args) throws IOException {
String json = "{\"username\":\"user1\",\"password\":\"123456\",\"country\":\"US\",\"creditCardNumber\":\"1283-1238-0458-3458\"}";
Gson gson = new Gson();
User user = gson.fromJson(json, User.class);
List<String> fieldNames = Arrays.asList("password", "creditCardNumber");
System.out.println(mask(user, fieldNames, "XXXXXXX"));
}
public static String mask(Object object, List<String> fieldNames, String mask) {
Field[] fields = object.getClass().getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
if (fieldNames.contains(fields[i].getName())) {
try {
fields[i].setAccessible(true);
if (fields[i].get(object) != null) {
fields[i].set(object, mask);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
Gson gson = new Gson();
return gson.toJson(object);
}
I like the above solution to mask using reflection but wanted to extend same for other field types and saving masked field to unmask again.
Create annotation #MaskedField on top of field.
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.FIELD)
public #interface MaskedField {
}
public <T> Map<String,? super Object> maskObjectFields(T object){
Map<String,? super Object> values = new HashMap<>();
Arrays.stream(object.getClass().getDeclaredFields()).filter(field->null != field.getAnnotation(MaskedField.class)).
forEach(annotatedField->{
try {
if(annotatedField.getType().isAssignableFrom(String.class)) {
annotatedField.setAccessible(true);
values.put(annotatedField.getName(),annotatedField.get(object));
annotatedField.set(object, maskString((String) annotatedField.get(object)));
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
});
return values;
}
public <T> void unMaskObjectFields(T object,Map values){
Arrays.stream(object.getClass().getDeclaredFields()).filter(field->null != field.getAnnotation(MaskedField.class)).
forEach(annotatedField->{
try {
annotatedField.setAccessible(true);
annotatedField.set(object,values.get(annotatedField.getName()));
} catch (IllegalAccessException e) {
e.printStackTrace();
}
});
}
private String maskString(String value){
if(Objects.isNull(value)) return null;
return null; //TODO: your logic goes here for masking
}
I'm trying to figure out how to convert a Jackson object into a JSONObject?
What I've tried, however I don't believe this is the correct approach.
public JSONObject toJSON() throws IOException {
ObjectMapper mapper = new ObjectMapper();
return new JSONObject(mapper.writeValueAsString(new Warnings(warnings)));
}
The way you are doing is work fine, because i also use that way to make a JSONobject.
here is my code
public JSONObject getRequestJson(AccountInquiryRequestVO accountInquiryRequestVO) throws JsonGenerationException, JsonMappingException, IOException {
ObjectMapper mapper = new ObjectMapper();
JSONObject jsonAccountInquiry;
jsonAccountInquiry=new JSONObject(mapper.writeValueAsString(accountInquiryRequestVO));
return jsonAccountInquiry;
}
its working fine for me. but you can always use JsonNode also
here is the sample code for that
JsonNode jsonNode=mapper.valueToTree(accountInquiryRequestVO);
its very easy to use.
Right now, you are serializing your Pojo to a String, then parsing that String and converting it into a HashMap style object in the form of JSONObject.
This is very inefficient and doesn't accomplish anything of benefit.
Jackson already provides an ObjectNode class for interacting with your Pojo as a JSON object. So just convert your object to an ObjectNode. Here's a working example
public class Example {
public static void main(String[] args) throws Exception {
Pojo pojo = new Pojo();
pojo.setAge(42);
pojo.setName("Sotirios");
ObjectMapper mapper = new ObjectMapper();
ObjectNode node = mapper.valueToTree(pojo);
System.out.println(node);
}
}
class Pojo {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Otherwise, the way you are doing it is fine.
I want my JSON to look like this:
{
"information": [{
"timestamp": "xxxx",
"feature": "xxxx",
"ean": 1234,
"data": "xxxx"
}, {
"timestamp": "yyy",
"feature": "yyy",
"ean": 12345,
"data": "yyy"
}]
}
Code so far:
import java.util.List;
public class ValueData {
private List<ValueItems> information;
public ValueData(){
}
public List<ValueItems> getInformation() {
return information;
}
public void setInformation(List<ValueItems> information) {
this.information = information;
}
#Override
public String toString() {
return String.format("{information:%s}", information);
}
}
and
public class ValueItems {
private String timestamp;
private String feature;
private int ean;
private String data;
public ValueItems(){
}
public ValueItems(String timestamp, String feature, int ean, String data){
this.timestamp = timestamp;
this.feature = feature;
this.ean = ean;
this.data = data;
}
public String getTimestamp() {
return timestamp;
}
public void setTimestamp(String timestamp) {
this.timestamp = timestamp;
}
public String getFeature() {
return feature;
}
public void setFeature(String feature) {
this.feature = feature;
}
public int getEan() {
return ean;
}
public void setEan(int ean) {
this.ean = ean;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
#Override
public String toString() {
return String.format("{timestamp:%s,feature:%s,ean:%s,data:%s}", timestamp, feature, ean, data);
}
}
I just missing the part how I can convert the Java object to JSON with Jackson:
public static void main(String[] args) {
// CONVERT THE JAVA OBJECT TO JSON HERE
System.out.println(json);
}
My Question is: Are my classes correct? Which instance do I have to call and how that I can achieve this JSON output?
To convert your object in JSON with Jackson:
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
String json = ow.writeValueAsString(object);
I know this is old (and I am new to java), but I ran into the same problem. And the answers were not as clear to me as a newbie... so I thought I would add what I learned.
I used a third-party library to aid in the endeavor: org.codehaus.jackson
All of the downloads for this can be found here.
For base JSON functionality, you need to add the following jars to your project's libraries:
jackson-mapper-asl
and
jackson-core-asl
Choose the version your project needs. (Typically you can go with the latest stable build).
Once they are imported in to your project's libraries, add the following import lines to your code:
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.map.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
With the java object defined and assigned values that you wish to convert to JSON and return as part of a RESTful web service
User u = new User();
u.firstName = "Sample";
u.lastName = "User";
u.email = "sampleU#example.com";
ObjectMapper mapper = new ObjectMapper();
try {
// convert user object to json string and return it
return mapper.writeValueAsString(u);
}
catch (JsonGenerationException | JsonMappingException e) {
// catch various errors
e.printStackTrace();
}
The result should looks like this:
{"firstName":"Sample","lastName":"User","email":"sampleU#example.com"}
Just follow any of these:
For jackson it should work:
ObjectMapper mapper = new ObjectMapper();
return mapper.writeValueAsString(object);
//will return json in string
For gson it should work:
Gson gson = new Gson();
return Response.ok(gson.toJson(yourClass)).build();
You could do this:
String json = new ObjectMapper().writeValueAsString(yourObjectHere);
This might be useful:
objectMapper.writeValue(new File("c:\\employee.json"), employee);
// display to console
Object json = objectMapper.readValue(
objectMapper.writeValueAsString(employee), Object.class);
System.out.println(objectMapper.writerWithDefaultPrettyPrinter()
.writeValueAsString(json));
You can use Google Gson like this
UserEntity user = new UserEntity();
user.setUserName("UserName");
user.setUserAge(18);
Gson gson = new Gson();
String jsonStr = gson.toJson(user);
Well, even the accepted answer does not exactly output what op has asked for. It outputs the JSON string but with " characters escaped. So, although might be a little late, I am answering hopeing it will help people! Here is how I do it:
StringWriter writer = new StringWriter();
JsonGenerator jgen = new JsonFactory().createGenerator(writer);
jgen.setCodec(new ObjectMapper());
jgen.writeObject(object);
jgen.close();
System.out.println(writer.toString());
Note: To make the most voted solution work, attributes in the POJO have to be public or have a public getter/setter:
By default, Jackson 2 will only work with fields that are either
public, or have a public getter method – serializing an entity that
has all fields private or package private will fail.
Not tested yet, but I believe that this rule also applies for other JSON libs like google Gson.
public class JSONConvector {
public static String toJSON(Object object) throws JSONException, IllegalAccessException {
String str = "";
Class c = object.getClass();
JSONObject jsonObject = new JSONObject();
for (Field field : c.getDeclaredFields()) {
field.setAccessible(true);
String name = field.getName();
String value = String.valueOf(field.get(object));
jsonObject.put(name, value);
}
System.out.println(jsonObject.toString());
return jsonObject.toString();
}
public static String toJSON(List list ) throws JSONException, IllegalAccessException {
JSONArray jsonArray = new JSONArray();
for (Object i : list) {
String jstr = toJSON(i);
JSONObject jsonObject = new JSONObject(jstr);
jsonArray.put(jsonArray);
}
return jsonArray.toString();
}
}