JsonMappingException: Already had POJO for id - rest

I have an error when trying to work with #JsonIdentityInfo jackson annotation. When I try to deserialize the object I get the following exception:
Could not read JSON: Already had POJO for id (java.lang.Integer) [1] (through reference chain: eu.cobiz.web.domain.Site["operators"]->eu.yavix.web.domain.Account["image"]->eu.cobiz.web.domain.Image["#Image"]);nested exception is com.fasterxml.jackson.databind.JsonMappingException: Already had POJO for id (java.lang.Integer) [1] (through reference chain: eu.yavix.web.domain.Site["operators"]->eu.cobiz.web.domain.Account["image"]->eu.cobiz.web.domain.Image["#Image"])
The JSON I am trying to deserialize looks like:
{
"#Site": 1,
"siteId": 1,
"name": "0",
"address": {
"#Address": 2,
"addressId": 4,
"number": "22"
},
"operators": [
{
"accountId": 1,
"email": "user982701361#yavix.eu",
"image": {
"#Image": 1,
"imageId": 1,
"uri": "http://icons.iconarchive.com/icons/deleket/purple-monsters/128/Alien-awake-icon.png"
}
},
{
"accountId": 2,
"email": "user174967957#yavix.eu",
"image": {
"#Image": 2,
"imageId": 2,
"uri": "http://icons.iconarchive.com/icons/deleket/purple-monsters/128/Alien-awake-icon.png"
}
}
]
}
My domain object is annotated with
#JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, property = "#Image")
The problem arises on #Id annotation since if I remove the annotation the problem disappears (as I did for account) but on my understanding the new feature is useful for cyclic dependencies which is useful for me in other scenarios. There shouldn't be a conflict between the 2 images since they are different objects.
How can I solve this or what is the problem?

You should use scope parameter when annotating the ids. Then the de-serializer would make sure the id is unique within the scope.
From Annotation Type JsonIdentityInfo:
Scope is used to define applicability of an Object Id: all ids must be unique within their scope; where scope is defined as combination of this value and generator type.
e.g.
#JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class,property="#id", scope = Account.class)

To avoid id conflict try to use ObjectIdGenerators.PropertyGenerator.class or ObjectIdGenerators.UUIDGenerator.class instead of ObjectIdGenerators.IntSequenceGenerator.class

Related

Strapi API Rest V 3.6.8 how to search posts by title?

I have installed version 3.6.8 of Strapi
In the docs for v3.x
https://strapi.gitee.io/documentation/v3.x/content-api/parameters.html#filter
Filters are used as a suffix of a field name:
No suffix or eq: Equals
ne: Not equals
lt: Less than
gt: Greater than
lte: Less than or equal to
gte: Greater than or equal to
in: Included in an array of values
nin: Isn't included in an array of values
contains: Contains
ncontains: Doesn't contain
containss: Contains case sensitive
ncontainss: Doesn't contain case sensitive
null: Is null/Is not null
And I can see those examples
GET /restaurants?_where[price_gte]=3
GET /restaurants?id_in=3&id_in=6&id_in=8
etc..
So I tried
/posts?_where[title_contains]=foo
/posts?title_contains=foo
And I also tried the "new way" in V4
/posts?filters[title][contains]=foo
But all of this attempts return all the post, exactly the same than just doing
/posts?
Any idea how to filter by post title and/or post body?
Almost there my friend! The issue you are facing called deep filtering (please follow the link for documentation).
In Short: the title field is located inside the attributes object for each item
Your items may look something similar to this:
{
"data": [
{
"id": 1,
"attributes": {
"title": "Restaurant A",
"description": "Restaurant A's description"
},
"meta": {
"availableLocales": []
}
},
{
"id": 2,
"attributes": {
"title": "Restaurant B",
"description": "Restaurant B's description"
},
"meta": {
"availableLocales": []
}
},
]
}
And therefor the filter should be
/api/posts?filters[attributes][title][$contains]=Restaurant
Also note:
the $ sign that should be included for your operator (in our case contains)
the api prefix you should use before the plural api id (e.g. posts, users, etc.)
you may prefer using $containsi operator in order to ignore upper and lower case letters (better for searching operations)
Let me know if it worked for you!

How to map a json string into object type in sink transformation

Using Azure Data Factory and a data transformation flow. I have a csv that contains a column with a json object string, below an example including the header:
"Id","Name","Timestamp","Value","Metadata"
"99c9347ab7c34733a4fe0623e1496ffd","data1","2021-03-18 05:53:00.0000000","0","{""unit"":""%""}"
"99c9347ab7c34733a4fe0623e1496ffd","data1","2021-03-19 05:53:00.0000000","4","{""jobName"":""RecipeB""}"
"99c9347ab7c34733a4fe0623e1496ffd","data1","2021-03-16 02:12:30.0000000","state","{""jobEndState"":""negative""}"
"99c9347ab7c34733a4fe0623e1496ffd","data1","2021-03-19 06:33:00.0000000","23","{""unit"":""kg""}"
Want to store the data in a json like this:
{
"id": "99c9347ab7c34733a4fe0623e1496ffd",
"name": "data1",
"values": [
{
"timestamp": "2021-03-18 05:53:00.0000000",
"value": "0",
"metadata": {
"unit": "%"
}
},
{
"timestamp": "2021-03-19 05:53:00.0000000",
"value": "4",
"metadata": {
"jobName": "RecipeB"
}
}
....
]
}
The challenge is that metadata has dynamic content, meaning, that it will be always a json object but the content can vary. Therefore I cannot define a schema. Currently the column "metadata" on the sink schema is defined as object, but whenever I run the transformation I run into an exception:
Conversion from ArrayType(StructType(StructField(timestamp,StringType,false),
StructField(value,StringType,false), StructField(metadata,StringType,false)),true) to ArrayType(StructType(StructField(timestamp,StringType,true),
StructField(value,StringType,true), StructField(metadata,StructType(StructField(,StringType,true)),true)),false) not defined
We can get the output you expected, we need the expression to get the object Metadata.value.
Please ref my steps, here's my source:
Derived column expressions, create a JSON schema to convert the data:
#(id=Id,
name=Name,
values=#(timestamp=Timestamp,
value=Value,
metadata=#(unit=substring(split(Metadata,':')[2], 3, length(split(Metadata,':')[2])-6))))
Sink mapping and output data preview:
The key is that your matadata value is an object and may have different schema and content, may be 'value' or other key. We only can manually build the schema, it doesn't support expression. That's the limit.
We can't achieve that within Data Factory.
HTH.

Magento 2 REST API Customer Custom Attribute

The Magento 2 REST API Documentation explains a way to set custom_attributes on a customer when updating or creating it. http://devdocs.magento.com/swagger/index_20.html#/
Unfortunately I couldn't get this to work...
My POST and PUT JSON request data is :
{
"customer": {
"custom_attributes": [
{
"attribute_code": "firstname",
"value": "TEST"
}
],
"email": "someone#exaxmple.com",
"extension_attributes": [],
"firstname": "Someone",
"gender": null,
"lastname": "Else",
"middlename": null,
"taxvat": null,
"website_id": "1"
}
}
The Customer is created but the Firstname is not "TEST".
Is there anyone who had the same problem and fixed it? Please let me know how.
My best guess is that, since Firstname is an existing Out-Of-The-Box attribute - the OOTB attribute name-value mapping assignment will take precedence.
Could you try again, with a unique custom attribute name (i.e. something that doesn't clash with OOTB attribute names)
You will need to DEFINE a custom-customer-attribute before you can use the M2 API to perform operations on that custom-customer-attribute.
This StackExchange thread - https://magento.stackexchange.com/questions/88245/magento2-create-a-customer-custom-attribute - has additional information on how to go about setting up a custom-customer-attribute.

Get null property when trying to use JSON views on rest Controller just extending from RestfulController

I'm trying out JSON views, not on top of domain class using #Resource, but by creating a RestfulController and trying to render that using JSON views. I've added all the relevant dependencies in build config.
I have a domain Post class like this (which I didn't want to directly expose)
class Post implements Serializable {
Map comments
User user
Venue venue
String description
Rating rating //should this be an enum?
LocalDateTime dateCreated
LocalDateTime lastUpdated
static belongsTo = [user:User]
static hasOne = [rating:Rating]
static constraints = {
venue nullable:true
comments nullable:true
description nullable:true
rating nullable:true, lazy:false
}
static mapping = {
//set the sort order for Posts - default using newest post first
sort dateCreated :"desc"
}
}
So I then created a default RestfulController like this:
class PostRestController extends RestfulController {
static responseFormats = ["json", "xml"]
//constructor - tells rest controller which domain class to scaffold
PostRestController() {
super (Post)
}
}
I'm not overriding any of the default scaffolding methods here.
When I used a rest client to access the default (I've mapped /api/posts (resources: postRest in the UrlMappings). When I access the URL with my REST client I got the full dump of the Post (including comments field persisted in a map) - this looks like this in my rest client - all OK:
[
{
"id": 1,
"comments": {
"view": "lovely"
},
"dateCreated": {
"class": "java.time.LocalDateTime",
"dayOfMonth": 7,
"dayOfWeek": {
"enumType": "java.time.DayOfWeek",
"name": "TUESDAY"
},
"dayOfYear": 66,
"hour": 19,
"minute": 15,
"month": {
"enumType": "java.time.Month",
"name": "MARCH"
},
"monthValue": 3,
"nano": 263000000,
"second": 10,
"year": 2017,
"chronology": {
"calendarType": "iso8601",
"class": "java.time.chrono.IsoChronology",
"id": "ISO"
}
},
"description": null,
"lastUpdated": {
"class": "java.time.LocalDateTime",
"dayOfMonth": 7,
"dayOfWeek": {
"enumType": "java.time.DayOfWeek",
"name": "TUESDAY"
},
"dayOfYear": 66,
"hour": 19,
"minute": 15,
"month": {
"enumType": "java.time.Month",
"name": "MARCH"
},
"monthValue": 3,
"nano": 263000000,
"second": 10,
"year": 2017,
"chronology": {
"calendarType": "iso8601",
"class": "java.time.chrono.IsoChronology",
"id": "ISO"
}
},
"rating": null,
"user": {
"id": 1
},
"venue": null
}
],
I then tried to add JSON views on top of this in the grails-app/views/postRest folder.
I did a really simple template _post.gson like this:
model {
Post post
}
json {
comments post.comments
description post.description
//rating post.rating
userWhoPosted "${post?.user}"
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MMM-dd")
def when = post.dateCreated.format(formatter)
created when
}
I then added an index.gson to render the template:
model {
List<Post> postList
}
//call the template to iterate over the postList to produce the output
json g.render(postList)
This breaks the server with this stacktrace and a 500 error to the REST client. If I comment out the line in_post.gson relating to user it all works. Leave it in and it fails:
Caused by: grails.views.ViewRenderException: Error rendering view: null
at grails.views.AbstractWritableScript.writeTo(AbstractWritableScript.groovy:43)
at grails.views.mvc.GenericGroovyTemplateView.renderMergedOutputModel(GenericGroovyTemplateView.groovy:73)
at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:303)
at grails.views.mvc.renderer.DefaultViewRenderer.render(DefaultViewRenderer.groovy:111)
at grails.artefact.controller.RestResponder$Trait$Helper.internalRespond(RestResponder.groovy:188)
at grails.artefact.controller.RestResponder$Trait$Helper.respond(RestResponder.groovy:62)
at grails.rest.RestfulController.index(RestfulController.groovy:64)
at grails.transaction.GrailsTransactionTemplate$2.doInTransaction(GrailsTransactionTemplate.groovy:96)
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133)
at grails.transaction.GrailsTransactionTemplate.execute(GrailsTransactionTemplate.groovy:93)
... 4
If I comment out the post.user (and ratings reference) it works OK, but when I try and post the post.user it fails with the above. There was a note in the docs about ensuring that your query pulled the refs with a fetch join - so I tried to provide a override to ensure I returned the fetch join - all I get is empty returned to the client:
class PostRestController extends RestfulController {
static responseFormats = ["json", "xml"]
//constructor - tells rest controller which domain class to scaffold
PostRestController() {
super (Post)
}
def index() {
Collection<Post> res = Post.list([fetch:[user:"join",rating:"join"]])
res
}
}
Why when I do it without the JSON view it works fine and when I use the JSON view I can't get the output including references? I checked the list request and it returns the list successfully in the debugger - but breaks in the rendering.
If I can get this to work, JSON views on Grails 3.2.6 looks pretty nice.
Aaargh - think this issue is with jsonViews 1.1.5 - its not ready for java 8 LocalDateTime.
i saw a trace on stackoverflow see topic
hibernate will now take localdateTime in your domain classes - that works. But the json template rendering wont, even if you add the java8 plugin.
So i went back into domain class changed my LocalDateTime back to Date, also changed the json template to use the older SimpleDateTime format (instead of DateTimeFormatter) and re ran - low and behold it worked.
I'll be really glad when we can say grails is properly java8 ready.
apparently json views requires feature enablement which is due in json views 2 (think this is an M2 right now) - so i've had to revert to java 7 Date until then.
blimey another lost day in the weeds.

datatype of complextype entity is null when returning an array of complex types

We have created a complextype field "carriers" which is an array of Carrier objects. See below metadata
"dataProperties": [
{
"name": "carriers",
"complexTypeName":"Carrier#Test",
"isScalar":false
}]
The Carrier entity is defined as below:
{
"shortName": "Carrier",
"namespace": "Test",
"isComplexType": true,
"dataProperties": [
{
"name": "Testing",
"isScalar":true,
"dataType": "String"
}
]
}
We are trying to return an array of complextype in breeze from a REST service call. We get an error in breeze.debug.js in the method proto._updateTargetFromRaw. The error is because the datatype is null.
Any idea how to fix this issue?
I'm guessing the problem is in your "complexTypeName". You wrote "Carrier#Test" when I think you meant to write "Carrier:#Test". The ":#" combination separates the "short name" from the namespace; you omitted the colon.
Hope that's the explanation.