Default for a missing field when deserializing Json with Jerkson - json

When parsing Json with the Jerkson library following the example in the docs:
case class Person(id: Long, name: String)
parse[Person]("""{"id":1,"name":"Coda"}""") //=> Person(1,"Coda")
If I try and deserialize Json that doesn't contain both the id and the name fields then an error is thrown saying they are needed. Is there a way of setting it up so that if the following Json for a Person was parsed:
{"id":2}
The name field could be defaulted to "John". (I thought this might be possible by setting a default in the parameter in the case class but no luck)

Check out this pull request I did for the Jerkson library. It adds support for case class default parameters.
Pay heed to user ksvladimir's comment, though, which I haven't had time to add to the pull request. (I'll update this answer when I do)

Related

Spring REST - String Serialization - bug or feature?

I found a very strange behavior in spring rest.
Having an endpoint like the following
#GetMapping("/foo")
public String foo() {
return "bar";
}
returns the value bar. Sounds correct, but this is not a valid json, the effective result should be "bar" (note the ""). One might argue that spring expects that if a method returns a string, you have already manually serialized the object, but if all other objects are serialized by spring, then i would expect to have a special way to tell that its already serialized but the default way should be to serialize the value.
Maybe i'm missing something here, that's the reason why i didn't created a ticket in the spring issue tracker jet.
Unregistering the StringHttpMessageConverter as described in this answer should do the trick: https://stackoverflow.com/a/37906098/505621
While not really an answer, there are 2 possible workarounds:
Encode it yourself
Just add the required quotation mark explicitly to the response string \".
This could for example be done by using JSONObject.quote(yourString).
Wrapping
Wrap your string into a simple object or custom class. Then Jackson knows what to do with it.
Collections.singletonMap("value", yourString);

Scala, Json & Spring Boot Rest

I am building a Rest API using spring boot and Scala based on the below suggestion. I am successfully able to call the methods in Scala but the case class is not working the way it is designed.
When I try to create a Json using net.liftweb.json, I am getting additional string as "$outer":{}. I don't want this additional string in my output.
Note that the spring boot is expecting class instead of object. I suspect this could be an issue. Can you help me on this.
My case class looks like this:
case class BasicSrch(size: String, query: Match)
Erroneous output
{"$outer":{},"size":"10","query":{"$outer":{},"match":{"$outer":{},"_all":{"$outer":{},"query":"SNOW","operator":"and"}}}}
Expected Output
{"size":"10","query":{"match":{"_all":{"query":"VALLE","operator":"and"}}}}
If you are writing UTF-8 encoded JSON to the byte array or OutputStream then try jsoniter-scala: https://github.com/plokhotnyuk/jsoniter-scala
It will not serialize any other fields except those which are defined in a primary constructor of the case class.

io.vertx.core.json.JsonObject: How to get the type of the value for given key?

I'm using the following package for JsonObject:
http://vertx.io/docs/apidocs/io/vertx/core/json/JsonObject.html
If I get a JsonObject with key 'fieldName' and I want to get its value, I have to use functions such as 'getString', 'getInteger', 'getArray' etc. I mean that I have to know in advanced the type of the value. What happens if I don't know it?
Is there any generic function of retrieving value from JsonObject without knowing its type?
Use getValue(String).
It returns an Object then you can test the type and cast accordingly.
Notes for the comments: Checking the code on GitHub, looks like the getField(String) method is present in the 2.x branch. Looks like getValue(String) is delegated to getField(String) method (see the code). As of August 2017, there's no getField(String) in the master (see the code).

Spray.io - Removing fields from response

I've built a RESTful API using Spray.io.
It contains a number of endpoints, each of which returns JSON.
I use the Spray JSON marshaller to marshal my internal objects to JSON which are returned to the user. So I have something similar to...
respondWithMediaType(`application/json`) {
complete(MyResponse(username, password))
}
Where MyResponse is a case class...
case class MyResponse(username:String, password:String)
However, I want to pick the fields that are returned in the response. So in this case I want to remove the "password" field before it is returned.
Whats the best way to do this with Spray?
Thanks
Posting an answer to close question. Went with Yuvals suggestion above (he didn't add as answer)...
"Why not create PasswordLessResponse case class, instead of jumping hooks to deserialize MyResponse in different ways"
and just created the relevant case classes and marshallers, populated and returned where needed.
Thanks Yuval!

What this the best way to ignore unwanted fields in a JSON payload from a PUT/PATCH using Golang?

I have a situation where people consuming our API will need to do a partial update in my resource. I understand that the HTTP clearly specifies that this is a PATCH operation, even though people on our side are used to send a PUT request for this and that's how the legacy code is built.
For exemplification, imagine the simple following struct:
type Person struct {
Name string
Age int
Address string
}
On a POST request, I will provide a payload with all three values (Name, Age, Address) and validate them accordingly on my Golang backend. Simple.
On a PUT/PATCH request though, we know that, for instance, a name never changes. But say I would like to change the age, then I would simply send a JSON payload containing the new age:
PUT /person/1 {age:30}
Now to my real question:
What is the best practice to prevent name from being used/updated intentionally or unintentionally modified in case a consumer of our API send a JSON payload containing the name field?
Example:
PUT /person/1 {name:"New Name", age:35}
Possible solutions I thought of, but I don't actually like them, are:
On my validator method, I would either forcibly remove the unwanted field name OR respond with an error message saying that name is not allowed.
Create a DTO object/struct that would be pretty much an extension of my Person struct and then unmarshall my JSON payload into it, for instance
type PersonPut struct {
Age int
Address string
}
In my opinion this would add needless extra code and logic to abstract the problem, however I don't see any other elegant solution.
I honestly don't like those two approaches and I would like to know if you guys faced the same problem and how you solved it.
Thanks!
The first solution your brought is a good one. Some well known frameworks use to implement similar logic.
As an example, latests Rails versions come with a built in solution to prevent users to add extra data in the request, causing the server to update wrong fields in database. It is a kind of whitelist implemented by ActionController::Parameters class.
Let's suppose we have a controller class as bellow. For purpose of this explanation, it contains two update actions. But you won't see it in real code.
class PeopleController < ActionController::Base
# 1st version - Unsafe, it will rise an exception. Don't do it
def update
person = current_account.people.find(params[:id])
person.update!(params[:person])
redirect_to person
end
# 2nd version - Updates only permitted parameters
def update
person = current_account.people.find(params[:id])
person.update!(person_params) # call to person_params method
redirect_to person
end
private
def person_params
params.require(:person).permit(:name, :age)
end
end
Since the second version allows only permitted values, it'll block the user to change the payload and send a JSON containing a new password value:
{ name: "acme", age: 25, password: 'account-hacked' }
For more details, see Rails docs: Action Controller Overview and ActionController::Parameters
If the name cannot be written it is not valid to provide it for any update request. I would reject the request if the name was present. If I wanted to be more lenient, I might consider only rejecting the request if name is different from the current name.
I would not silently ignore a name which was different from the current name.
This can be solved by decoding the JSON body into a map[string]json.RawMessage first. The json.RawMessage type is useful for delaying the actual decoding. Afterwards, a whitelist can be applied on the map[string]json.RawMessage map, ignoring unwanted properties and only decoding the json.RawMessages of the properties we want to keep.
The process of decoding the whitelisted JSON body into a struct can be automated using the reflect package; an example implementation can be found here.
I am not proficient on Golang but I believe a good strategy would be converting your name field to be a read-only field.
For instance, in a strictly object-oriented language as Java/.NET/C++ you can just provide a Getter but not a Setter.
Maybe there is some accessor configuration for Golang just like Ruby has....
If it is read-only then it shouldn't bother with receiving a spare value, it should just ignore it. But again, not sure if Golang supports it.
I think the clean way is to put this logic inside the PATCH handler. There should be some logic that would update only the fields that you want. Is easier if you unpack into a map[string]string and only iterate over the fields that you want to update. Additionally you could decode the json into a map, delete all the fields that you don't want to be updated, re-encode in json and then decode into your struct.