convert json to java POJO using stream api - gson

I have a json file and using below code to convert json into java POJO
reader = new JsonReader(new InputStreamReader(responseStream, "UTF-8"));
Gson gson = new GsonBuilder().create();
reader.beginObject();
while (reader.hasNext()) {
Example st = gson.fromJson(reader, Example.class);
}
my json structure is as:
{
"$id": "students.json",
"type": "object",
"properties": {
"project": {
"$id": "project",
"projectList": [
"ABC"
]
},
"students": {
"$id": "/properties/students",
"type": "array",
"subelements": {
"properties": {
"id": {
"$id": "/properties/students/subelements/properties/id",
"examples": [
"Y"
]
},
"dep": {
"$id": "/properties/students/subelements/properties/dep",
"examples": [
"X"
]
}
},
"required": [
"id",
"dep"
]
}
}
},
"required": [
"project"
]
}
And I only need students.subelements.id.examples[0] and students.subelements.dep.examples[0] from list of students
currently my java object classes are:
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonPropertyOrder({
"project",
"elements"
})
public class Example {
/**
* The project
* (Required)
*
*/
#JsonProperty("project")
#JsonPropertyDescription("The project code")
private String project;
#JsonProperty("elements")
private List<Student> elements = null;
#JsonIgnore
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
}
//student class
public class Student{
private String id;
private String dep;
}
and I am facing below exception:
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was NAME at line 2 column 4 path $.
so please help me what will be my exact java object class according to provided json and I will get only required fields from that class ?

Reason for error
To begin, the reason for the error is that, after you first call reader.beginObject();, the JSON reader will go to second line "$id", which is a NAME type for JSONToken.
And gson.fromJson(reader, Student.class); is expecting the next JSON value is of BEGIN_OBJECT type, hence the error occur.
Solution
Since only a small part from the JSON is required, and the path is not trivial, we can not create a POJO to retrieve data by direct mapping. As #user10375692 suggests, we can implement JsonDeserializer interface for more flexible mapping. In the deserialize method, we can use JSONObject API to retrieve data from specific path. Following is an example.
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
public class JsonToPojo {
public static void main(String[] args) {
String json = getJson();
GsonBuilder gsonBuilder = new GsonBuilder();
JsonDeserializer<Example> deserializer = new JsonDeserializer<Example>() {
#Override
public Example deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
Example example = new Example();
JsonObject jsonObject = json.getAsJsonObject();
example.setProject(jsonObject.getAsJsonObject("properties").getAsJsonObject("project")
.getAsJsonArray("projectList").get(0).getAsString());
JsonObject subElementProperties = jsonObject.getAsJsonObject("properties").getAsJsonObject("students")
.getAsJsonObject("subelements").getAsJsonObject("properties");
JsonArray idExamples = subElementProperties.getAsJsonObject("id").getAsJsonArray("examples");
JsonArray depExamples = subElementProperties.getAsJsonObject("dep").getAsJsonArray("examples");
List<Student> students = new ArrayList<Student>();
for (int i = 0; i < idExamples.size(); i++) {
Student student = new Student();
student.setId(idExamples.get(i).getAsString());
student.setDep(depExamples.get(i).getAsString());
students.add(student);
}
example.setStudents(students);
return example;
}
};
gsonBuilder.registerTypeAdapter(Example.class, deserializer);
Gson customGson = gsonBuilder.create();
Example customObject = customGson.fromJson(json, Example.class);
System.out.println(customObject.getStudents() + ", " + customObject.getProject());
}
private static String getJson() {
return "{ "
+ " \"$id\": \"students.json\", "
+ " \"type\": \"object\", "
+ " \"properties\": { "
+ " \"project\": { "
+ " \"$id\": \"project\", "
+ " \"projectList\": [ "
+ " \"ABC\" "
+ " ] "
+ " }, "
+ " \"students\": { "
+ " \"$id\": \"subproject\", "
+ " \"type\": \"array\", "
+ " \"subelements\": { "
+ " \"properties\": { "
+ " \"id\": { "
+ " \"$id\": \"id\", "
+ " \"examples\": [ "
+ " \"Y\" "
+ " ] "
+ " }, "
+ " \"dep\": { "
+ " \"$id\": \"dep\", "
+ " \"examples\": [ "
+ " \"X\" "
+ " ] "
+ " } "
+ " }, "
+ " \"required\": [ "
+ " \"id\", "
+ " \"dep\" "
+ " ] "
+ " } "
+ " } "
+ " }, "
+ " \"required\": [ "
+ " \"project\" "
+ " ] "
+ "} ";
}
}

Related

For Loop Duplicating Results in Postman Data files - Using Collection Runner

This is in relation to my previous question: For Loop in Postman not Working as Expected.
This is my test data (saved as numbers.json ):
[
{
"numbers": 1422.39
},
{
"numbers": 429.01
}
]
I run this test in the Postman Runner.
My code is:
const jsonData = pm.response.json();
for (let i=0; i < jsonData.length; i++)
{
console.log("Response " + [i] + " data = " + data["numbers"]);
}
The output looks like this:
And if I use the code:
console.log("Response " + [i] + " data = " + data[i].numbers);
Then I will get this error:
TypeError: Cannot read property 'numbers' of undefined
My responseBody is (same as the data file - it is a copy, so that the numbers will match):
[
{
"numbers": 1422.39
},
{
"numbers": 429.01
}
]

Grpc-node: How to edit metadata in gRPC server and send back edited metadata to grpc-client?

Grpc-node: How to edit metadata and send back edited metadata to client?
Below is currently what I have at the moment, and it seems like the metadata can be passed to the grpc-client RPC method ('greetmath'), but I can't edit the metadata in the server and send it back to the client. It can only send back metadata that was originally created.
Is there anyway I can edit the metadata in the grpc server and send that edited metadata to the grpc client?
Greeter_server.js
const path = require('path');
const PROTO_PATH = path.join(__dirname, '../proto/greet.proto');
// console.log("Proto path: ", PROTO_PATH);
const protoLoader = require('#grpc/proto-loader') //require('#grpc/proto-loader')
const grpc = require('grpc')
//grpc service definition for greet
const greetProtoDefinition = protoLoader.loadSync(PROTO_PATH, {
keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true
});
const greetPackageDefinition = grpc.loadPackageDefinition(greetProtoDefinition).greet
function greetFunc(call, callback) {
var firstName = call.request.greeting.first_name;
var lastName = call.request.greeting.last_name;
callback(null, {result: "Hello " + firstName + " " + lastName});
}
function greetMath(call, callback) {
console.log("callback: ", call);
console.log("Meta data: ", call.metadata._internal_repr.somekey);
call.metadata._internal_repr.somekey.push('random');
var firstName = call.request.greeting.first_name;
var lastName = call.request.greeting.last_name;
let current = Number(process.hrtime.bigint());
console.log("call obj: ", call);
console.log("callback obj: ", callback);
callback(null, {result: "Hello " + firstName + " " + lastName + " current: " + current});
}
function main() {
const server = new grpc.Server()
server.addService(greetPackageDefinition.GreetService.service, {
greet: greetFunc,
greetMath: greetMath
});
server.bind("127.0.0.1:4000", grpc.ServerCredentials.createInsecure());
server.start();
console.log("Server Running at http://127.0.0.1:50051")
}
main()
greet.proto
syntax = "proto3";
package greet;
service GreetService {
//Unary API
rpc Greet (GreetRequest) returns (GreetResponse) {};
rpc GreetMath(GreetRequest) returns (GreetResponse) {};
}
message Greeting {
string first_name = 1;
string last_name = 2;
}
message GreetRequest {
Greeting greeting = 1;
}
message GreetResponse {
string result = 1;
}
greeter_client.js
const path = require('path');
const PROTO_PATH = path.join(__dirname, '../proto/greet.proto');
const protoLoader = require('#grpc/proto-loader') //require('#grpc/proto-loader')
const grpc = require('grpc')
//grpc service definition for greet
const greetProtoDefinition = protoLoader.loadSync(PROTO_PATH, {
keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true
});
const greetPackageDefinition = grpc.loadPackageDefinition(greetProtoDefinition).greet
const client = new greetPackageDefinition.GreetService("localhost:4000",
grpc.credentials.createInsecure()
)
function callGreetings() {
var request = {
greeting: {
first_name: "Jerry",
last_name: "Tom"
}
}
client.greet(request, (error, response) => {
if(!error) {
console.log("Greeting Response: ", response.result);
} else {
console.error(error)
}
})
}
function callGreetingsLogger() {
var request = {
greeting: {
first_name: "Jerry",
last_name: "Tom"
}
}
let meta = new grpc.Metadata();
meta.add('someKey', 'someVal');
let end;
let start = Number(process.hrtime.bigint());
client.greetMath(request, meta, (error, response) => {
if(!error) {
console.log("res: ", response);
console.log("metadata: ", meta);
console.log("Greeting Response: ", response.result);
end = Number(process.hrtime.bigint());
console.log("start: ", start);
console.log("end: ", end);
console.log("end - start", (end - start)/ 1000000, "ms");
function getDateTime() {
var date = new Date();
var hour = date.getHours();
hour = (hour < 10 ? "0" : "") + hour;
var min = date.getMinutes();
min = (min < 10 ? "0" : "") + min;
var sec = date.getSeconds(); sec = (sec < 10 ? "0" : "") + sec;
var year = date.getFullYear();
var month = date.getMonth() + 1; month = (month < 10 ? "0" : "") + month;
var day = date.getDate(); day = (day < 10 ? "0" : "") + day;
return month + "/" + day + "/" + year + " | Time: " + hour + ":" + min + ":" + sec;
}
let currentTime = getDateTime();
console.log("Current time: ", currentTime);
} else {
console.error(error)
}
});
}
function main() {
callGreetings();
callGreetingsLogger();
}
main()
The question says "I can't edit the metadata in the server and send it back to the client". The code in the question edits the metadata, so I assume that that is the code you are trying to use to do that, but that is not sending the metadata because it never calls the sendMetadata method of the call. You need to call that method to send metadata back to the client.
In addition, you should not touch the _internal_repr of the metadata. The client code handles this correctly by calling meta.add(). The server code should do the same. So, instead of call.metadata._internal_repr.somekey you should write call.metadata.get('somekey') and instead of call.metadata._internal_repr.somekey.push('random') you should write call.metadata.add('somekey', 'random').
I suspect that you're trying to change the gRPC's internal metadata (call.metadata._internal_repr) and this is not permitted.
In Go(lang) for example, the only methods exposed for Metadata are e.g. GetMetadata() and there's intentionally no public mechanism to change this data.
You have some options:
Create a message type that you carry within your messages for metadata.
Consider Custom Options and Extensions if you're trying to extend the capabilities of gRPC.

ReferenceError in elasticsearch with javascript

I am experimenting with a node application for Elasticsearch. My code:
var esRequest = " {\n" +
" \"title\": {\n" +
" \"value\": \"java\"\n" +
" }\n" +
" }";
let body = {
size: 20,
from: 0,
query
}
body.query.match = JSON.parse(esRequest)
esClient.search({index:"myindex",body:body});
I get error as:
ReferenceError: query is not defined
Made this change, and it worked:
let body = {
size: 20,
from: 0,
query: {}
}
body.query.match = JSON.parse(esRequest)

how to select a field with a dinstinct with elasticsearch

I want to do something like this :
SELECT DISTINCT(CATEG) FROM TABLE;
I tried :
{
"fields" : ["category"],
"query": {
"match_all": {}
},"aggs":{
"by_category": {
"terms": {
"field": "category"
}
}
}
}
but don't work.
In my java code, i do
ElasticSearchInstance instance = ElasticSearchInstance.getInstance();
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("{\"fields\" : [\"category\"],"
+ "\"size\":0,\"aggs\":{ "
+ " \"by_category\": { "
+ " \"terms\": { "
+ " \"field\": \"category\",\"size\":0 "
+ " } } } "
+ "}");
SearchResult searchResult = instance.execute("String", stringBuilder.toString());
And my searchResult is :
{"took":1,"timed_out":false,"_shards":{"total":5,"successful":5,"failed":0},"hits":{"total":0,"max_score":0.0,"hits":[]},"aggregations":{"by_category":{"doc_count_error_upper_bound":0,"sum_other_doc_count":0,"buckets":[]}}}
My result should be "Blues" and "Other".
Any ideas ?
This could help you
SearchRequestBuilder srb = ClientInstance.getInstance().getClient().prepareSearch();
srb.setQuery(QueryBuilders.matchAllQuery()).addAggregation(AggregationBuilders.terms("by_category").field("category").size(0).order(Terms.Order.term(true))
Finally, I found it.
My query is :
{
"size": 0,
"aggs": {
"category": {
"terms": {
"field": "category"
}
}
}
}
In my java code, I use :
Search.Builder searchBuilder = new Search.Builder(stringBuilder.toString());
SearchResult searchResult = instance.execute(searchBuilder);
List<Entry> res = searchResult.getAggregations().getTermsAggregation("category").getBuckets();
I loop on my list to get the key !!

OData 4 web api 2 "No routing convention was found"

I'm trying to post object to odata action, here my code
public class DraftController : ODataController
{
public HttpResponseMessage Attachment([FromODataUri] string key, [FromBody] DraftApi d)
{
try
{
return Request.CreateResponse(HttpStatusCode.Created, "(POST ATTACHMENT) key: " + key + " - id: " + d.id + ", desc: " + d.description);
}
catch (Exception e)
{
return Request.CreateResponse(HttpStatusCode.InternalServerError, e.Message);
}
}
}
this is my model
public class DraftApi
{
[Key]
public string id { get; set; }
public string description { get; set; }
}
this is my OData route
config.MapODataServiceRoute(
routeName: "ODataDraft",
routePrefix: "odata/{namespace}",
model: BuildModel<DraftApi>("draft")
);
private static IEdmModel BuildModel<T>(string EntityName) where T : class
{
ODataConventionModelBuilder ODataBuilder = new ODataConventionModelBuilder();
ODataBuilder.EntitySet<T>(EntityName).EntityType.Name = EntityName;
ActionConfiguration attachment = ODataBuilder.EntityType<T>().Action("Attachment");
ODataBuilder.EnableLowerCamelCase();
return ODataBuilder.GetEdmModel();
}
my call is this
Url
http://127.0.0.1/mpssapi/odata/v1/draft('hhh')/Attachment
Headers
Content-Type: application/json
Payload
{id:"a", description: "abc"}
This is my response
{
"error": {
"code": ""
"message": "No HTTP resource was found that matches the request URI 'http://127.0.0.1/mpssapi/odata/v1/draft('hhh')/Attachment'."
"innererror": {
"message": "No routing convention was found to select an action for the OData path with template '~/entityset/key/unresolved'."
"type": ""
"stacktrace": ""
}-
}-
}
I have tried to add namespace to odata route but it doesn't work
any ideas?
thanks
The doc may help: http://odata.github.io/WebApi/#04-07-action-parameter-support
and call without namespace, you need to turn on UnqualifiedNameCall option like:
config.EnableUnqualifiedNameCall(true);

Resources