I need to generate an AVRO schema from an existing Java Model. I then want to use that schema to generate Java objects so I can replace my existing model with the generated one, making the schema the source of truth.
I am having a problem which I will try to illustrate with this example.
I have a basic Java class:
public class Car {
private String price;
private String engine;
public Car(String price, String engine) {
this.price = price;
this.engine = engine;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
public String getEngine() {
return engine;
}
public void setEngine(String engine) {
this.engine = engine;
}
}
I want to generate an avro schema which represents this class.
public static void main(String[] args) throws JsonMappingException {
System.out.println(generateAvroSchema());
}
public static String generateAvroSchema() throws JsonMappingException {
ObjectMapper mapper = new ObjectMapper(new AvroFactory());
AvroSchemaGenerator gen = new AvroSchemaGenerator();
mapper.acceptJsonFormatVisitor(Car.class, gen);
Schema schema = gen.getGeneratedSchema().getAvroSchema();
return schema.toString(true);
}
The result of this is:
{
"type" : "record",
"name" : "Car",
"namespace" : "app",
"fields" : [ {
"name" : "engine",
"type" : [ "null", "string" ]
}, {
"name" : "price",
"type" : [ "null", "string" ]
} ]
}
When the schema is generated the object attributes are ordered alphabetically. If I was to use this schema to generate a new java model, the constructor argument ordering would be different from the source.
My question is, is there any configuration I can use when generating the schema to preserve attribute ordering and not default to alphabetical?
Thanks
Ran into this issue as well, solved following https://github.com/fasterxml/jackson-dataformat-csv/issues/40
Basically calling mapper.disable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY); on the mapper.
Related
I am trying to map Entity with ManyToMany relationship to DTO.
public class SkillEntity {
#Id
#GeneratedValue(generator = "system-uuid")
#GenericGenerator(name = "system-uuid", strategy = "uuid")
private String id;
private String name;
#ManyToMany(mappedBy = "skills")
private Set<UnifiedOfferEntity> unifiedOffers = new HashSet<>();
#Data
public class SkillDTO {
private String name;
private Set<UnifiedOfferDTO> unifiedOffers;
}
And I have problem with mapping that Set. I did custom mapper and it works, I am getting resposne like below but I want to skip "skills" field in UnifiedOfferDTO.
{
"name": "REACT NATIVE",
"unifiedOffers": [
{
"companyName": "QLOC S.A.",
"title": "Tester",
"skills": null,
},
{
"companyName": "Apptension sp. z o.o.",
"title": "Junior Frontend Developer",
"skills": null,
}
]
}
I created typeMap:
modelMapper.typeMap(SkillEntity.class, SkillDTO.class)
.addMappings(m -> m.using(skillEntityUnifiedOffersListConverter)
.map(skillEntity -> skillEntity, SkillDTO::setUnifiedOffers))
and i would like to skip that field "skills" from unifiedOfferDTO but do not know if I should add mapper.skip or something else.
In my REST application there are a lot of post end points that are having enums inside https requests.
When I open swagger UI and check sample request for any of these post methods enum value is everywhere first value in one particular enum. So if I have enum called Fruits
public enum Fruits {
APPLE,
ORANGE
}
and another one
public enum Vegetables {
TOMATO,
POTATO
}
I am not able to see e.g. value "TOMATO" anywhere in http sample requests in swagger where Vegetables enum is used. Everywhere there is always "APPLE".
I'm editing question and giving exact example.
Here is one post method:
#PostMapping(path = "search")
public Result<Page<CountryCodeRecord>> searchCountryCodes(
#RequestBody PageableSearchRequest<CountryCodeQuery,CountryCodeOrder> pageableSearchRequest) {
return new Result<>(countryCodeFacade.search(pageableSearchRequest));
}
These are used classes:
public class PageableSearchRequest<T extends Query, S extends QueryOrder> implements Serializable {
private T query;
private SearchSort<S> searchSort;
private PageSelection pageSelection;
...
}
public class CountryCodeQuery implements Query, Serializable {
private String name;
private Boolean active;
//...
}
public enum CountryCodeOrder implements QueryOrder {
NAME("name"),
ACTIVE("active");
}
And this is swagger sample request:
{
"pageSelection": {
"pageNumber": 0,
"pageSize": 0
},
"query": {
"active": true,
"name": "string"
},
"searchSort": {
"orders": [
{
"orderBy": "**PA_NUMBER**",
"sortDirection": "ASC"
}
]
}
}
This line "orderBy": "PA_NUMBER" should be "orderBy": "NAME".
[
{
"articles": [
[
"2016-03-04",
6
],
[
"2016-03-05",
10
],
[
"2016-03-06",
11
]
],
"accession": "00000446-201301000-00018"
},
{
"articles": [
[
"2016-03-04",
1
],
[
"2016-03-08",
17
],
[
"2016-03-09",
10
]
],
"accession": "00000446-201301000-00019"
}]
List is input { "Accession"= "00000446-201301000-00018", "Date"= "635926464000000000","Rank" =2},{ "Accession" = "00000446-201301000-00019", "Date" = "635931648000000000","Rank" = 2}
I want json data exactly like this,data is coming from list and list is dynamically growing.Form list, I want all dates and rank club to gether for the same accession number.
I want to use newtonsoft json custom serlization to convert my list to json.
What you want to do does not need any Custom Formatter, you just have to re-structure your data, Here is an example for restructuring a list based on Entity class to the new required one.
class Entity
{
public string Accession { get; set; }
public string Date { get; set; }
public int Rank { get; set; }
}
Add this line if you need to read the list from Json
var list = JsonConvert.DeserializeObject<List<Entity>>(input);
Here is the code for changing the structure of data to array based articles.
var translatedAsArray = list.GroupBy(e => e.Accession)
.Select(g =>
new {
//change new 'object[]' to 'new' to make the article an object
//you can convert i.Date, i.Rank and g.Key to anything you want here
Articles = g.Select(i => new object[] { i.Date , i.Rank }),
Accessing = g.Key
}
);
var json = JsonConvert.SerializeObject(translatedAsArray, Formatting.Indented);
Model
public class FinalList
{
public string accession {get;set;}
public List<ArticlesDetails> Articles{get;set;}
}
public class ArticlesDetails
{
public DateTime Date{get;set;}
public int number{get;set;}
}
Use ObjectContent instead of StringContent so we let the formatter (i.e. JsonMediaTypeFormatter) to deal with the serialization and deserialization
In config
config.Formatters.Insert(0, new YourCustomFormatter());
config.Formatters.Insert(1, new JsonMediaTypeFormatter());
and disable post in your custom formatter so that JsonMediaTypeFormatter desrializes the complex data
I am trying to do one to many domain mapping in grails.Here are the two classes :
class TNDetails {
String tn
String tnpk
static hasMany = [iccid: ICCID]
static mapping = {
table 'ni_tn'
version false
tnpk column : 'TN_PK'
tn column: 'TN'
id column: 'TN_PK',name: 'tnpk'
}
}
class ICCID {
String sim
String customer
static belongsTo = [tn: TNDetails]
static mapping = {
table 'ni_sim'
version false
sim column: 'ICCID'
customer column: 'CUSTOMER'
tn column: 'TN_FK'
id column: 'SIM_PK'
}
}
The corresponding query can be written as : select TN,ICCID from ni_tn,ni_sim where ni_tn.TN_PK = ni_sim.RELATED_TN and tn_pk=1290.Now in my controller when i am fetch the details by passing tn_pk like this :
def index() {
def pk = params.tnPK
def details = TNDetails.findAll {
(tnpk == pk)
}
respond details
}
i get following result :
[
{
"class": "com.evolving.resource.tn.TNDetails",
"id": 1290,
"tnpk": "1290",
"iccid": [
{
"class": "com.evolving.resource.iccid.ICCID",
"id": 4209
}
],
"tn": "447400002035"
}
]
Now the problem here is it is not displaying the attributes sim and customer(from class ICCID).How do i display these two parameters also.What am i doing wrong here?
change your:
respond details
to:
JSON.use("deep") {
respond details as JSON
}
The Deep Converters fully render the associations (nested domainclass instances) and also handle circular relations (documentation)
I'm trying to display the # of "likes" of a user selected entity that has a facebook site. The url that's passed in is the entities facebook name:
public int GetLikes(string url)
{
string jsonString = new WebClient().DownloadString("http://graph.facebook.com/?ids=" + url);
Dictionary<string, dynamic> values = JsonConvert.DeserializeObject<Dictionary<string, dynamic>>(jsonString);
int keyValues = values.Count;
int likes = values["likes"];
return likes;
}
I get an error that "likes" is not found in the value. But it's clearly there. Below is a sample of the JSON data that's returned from facebook:
{
"disney": {
"about": "\"It's kind of fun to do the impossible.\" - Walt Disney",
"category": "Company",
"checkins": 26,
"description": "This Page is a place for our Fans. However, we do need to have certain rules. Please be aware that we do not accept or consider unsolicited idea submissions and, also, we must reserve the right to remove any posting or other material that we find off-topic, inappropriate or objectionable.",
"founded": "1923",
"is_published": true,
"talking_about_count": 543991,
"username": "Disney",
"website": "http://disney.com",
"were_here_count": 0,
"id": "11784025953",
"name": "Disney",
"link": "http://www.facebook.com/Disney",
"likes": 46622418,
"cover": {
"cover_id": "10152010506970954",
"source": "http://sphotos-d.ak.fbcdn.net/hphotos-ak-prn1/t1.0-9/s720x720/1960125_10152010506970954_1312297640_n.png",
"offset_y": 0,
"offset_x": 0
}
}
}
I have tried many different things. Getting and deserializing the JSON data isn't a problem but I haven't been able to find a way to get any of the elements. Any help is appreciated.
First Create a class that mimics your JSON string (object) structure:
public class JSONobject
{
public Disney = new Disney();
}
public class Disney
{
public string about { get; set; }
public string category{get;set;}
public int checkins = {get;set;}
........
public int likes = {get;set;}
........
public Cover = new Cover();
}
public class Cover
{
public int cover_id { get;set; }
........
}
Then, initialize the object as well as the serializer:
JSONobject jsonOb = new JSONobject();
JavaScriptSerializer serializer = new JavaScriptSerializer();
Finally, parse the jsonString into your defined class:
try
{
jsonOb = serializer.Deserialize<JSONobject>(jsonString);
//ViewBag.jsondecoded = "Yes";
}
catch (Exception e)
{
//ViewBag.jsonDecoded = "No" + ", Exception: " + e.Message.ToString();
}
Retrieving variables:
string about = jsonOb.Disney.about;
string category = jsonOb.Disney.category;
int checkins = jsonOb.Disney.checkins;
int likes = jsonOb.Disney.likes;
Cover cover = jsonOb.Disney.Cover;
Hope this helps.