REST services PATCH API example - java

I am trying to call the REST Webservices PATCH API, here is My JSON payload
[
{ "op":"replace", "path":"/values/Timestamp","value":"2016-10-28T15:25:43.511Z"},
{ "op":"replace", "path":"/values/Flag", "value":true },
{ "op":"replace", "path":"/values/Flow", "value":"Flow A"},
{"op":"replace", "path":"/values/Interests", "value":[ "Sports", "Book Reading" ] }
]
JSON Value attribute has different values with different data types. and I want to prepare Entity object(Java) and convert it into JSON and call REST end point.
now
I am not very sure
which is the best suitable data type I can choose for values attribute
I have referred following links but I didn't get enough details
Android REST API using PATCH method
https://www.rfc-editor.org/rfc/rfc5789#section-2.1
http://blog.earaya.com/blog/2013/05/30/the-right-way-to-do-rest-updates/
http://williamdurand.fr/2014/02/14/please-do-not-patch-like-an-idiot/
but I didn't get enough details.
any suggestion on this is really appriciated

Got the java object from the client and created another Java class with below properties and set the values
opn - string
path - String
value - Object
added above java objects to array list then used the GSON library to convert it into the array of JSON objects which will be accepted by patch api.
and please note the content type is application/json-patch+json

Related

How to combine JSON values in the response using Java

I am currently working on a school project. We have a series of response templates in JSON format that will take values from the request and then return it accordingly in the response when run in postman.
e.g
Request:
{
"Application_id":123456
}
Response:
{ "Application_id: 123456, TIMESTAMP: 20220501}
I am able to get these values in the response but the issue I am running accross now is figuring out how to combine 2 values in the request into one like so:
Request:
{
"Application_id":123456
"user_id_first_six": 456789
"user_id_last_four": 1234
}
Expected Response:
{ "Application_id: 123456, TIMESTAMP: 20220501, combined_id:456789****1234}
what I have tried is to put combined_id : "user_id_first_six"+******+"user_id_last_four" but this doesnt work.
Apologies if I cant be more specific as there are portions that I have left out due to confidentiality issues.
The easiest way to achieve this in Java would be to use JSONObject. In your Request-Handler, add two parameters of Type JSONObject and then merge them:
jsonObj.putAll(jsonObj1)
Thanks all for the guidance. I basically did what Knu8 suggested and extracted the values using Matcher+Regex (<(.*)>)(\W*)(<(.*)>) and converted them to strings and then used StringBuilder to append all the components together.

Compile time check while passing values to a function in Kotlin Android

I am taking a JSON file as input for a class and parsing the values using gson through respective data classes.
I want to call a function that takes a String value as an argument.
The string value allowed is decided from the values parsed from JSON file. Can I somehow check for that string value passed to the function at compile-time & give an error at compile-time?
Or If I can allow only certain values in the argument for the function based on the values from JSON
Detailed Explanation of use case:
I am building a SDK in which a the person using sdk inputs json String. The json is standardised and is parsed in my code.
{
"name": "Test",
"objects": [
{
"name": "object1",
"type": "object1"
}
]
}
Here name values and other values may vary based on the input by the developer using it but key remains same. But we need to call a function using the value in objects name parameter.
fun testMethod(objectName:String)
So developer calls the testMethod as testMethod(object1).
I need to validate object1 parameter based on json but is there any way possible restricting the test method parameter to object1 only & give error at compile time if the developer calls testMethod(obj1)
Right now I parse JSON & have checks inside the testMethod()
Sure it's possible to do, but somehow in different way, that you described. First of all, as you already mentioned this behavior could be done easily. For this purpose we have Objects.requireNotNull() or Guava.Preconditions(). At the same way you can define you checking but this will work on runtime only.
To do in compile time, you need to create Annotation Preprocessor. The same, as did in different libraries, and one of them, could be Lombok, with their NotNull and Nullable. Android annotation just provide mark and bound for IDE warning, but in their case they adding NotNull checking and throw exception for every annotation usage during compile time.
It's not an easy way, but it's what you are looking for.
No, it's impossible check it in compiler time. It's string handling, as numeric calculation.
In my app, I convert string to JSON and JSON to string, passing class descriptor. My aim is record JSON string in a text file to load in SQLite database. This code I've run in my desktop computer not in Android.
data class calcDescr (
...
)
val calc = CalcDescr(...)
// toJson: internal Kotlin data to JSON
val content = Gson().toJson(calc)
//==================
// Testing validity
// ================
// fromJson: JSON to internal Kotlin data.
// It needs pass the class descriptor. Uses *Java* token, but it's *Kotlin*
var testModel = Gson().fromJson(content, CalcDescr::class.java)
// toJson: internal Kotlin data to JSON again
var contentAgain = Gson().toJson(testModel)
// shoul be equal!
if (content == contentAgain) println("***ok***")
In my file, I write the variable content in a file

javax.json: Adding a value to a javax JsonValue

I am trying to add a value to a list of JsonValue. Is it possible to do this?
A bit of background, I am retrieving a Json response from a Rest API, within this Json is a list of Names like this:
{
"Name" : {Name1, Name2, Name3, ...}
}
I need to add another name to list so I can modify names through the Rest API. You are able to perform this task as I have it working in PowerShell, however I can not use PowerShell in the final program.
You can't modify JSONObject as it is immutable.
You might want to explore GSON API to update JSONObject.

Filtering field with array as JSON in logstash

I'm starting out to collect logs with logstash. The current setup consist of a Java server using logback as logging mechanism and logstash-logback-encoder, outputting the data in a neat JSON representation. The basics work just fine.
I would like to separate additional data in JSON format in separate fields (so each key of the JSON ends up in its own field). logstash-logback-encoder provides a mechanism for that to output such data in a json_mesage field. However this JSON string is placed into a JSON array. See here a sample formatted for better reading.
{
"#timestamp":"2014-03-25T19:34:11.586+01:00",
"#version":1,
"message":"Message{\"activeSessions\":0}",
"logger_name":"metric.SessionMetrics",
"thread_name":"scheduler-2",
"level":"INFO",
"level_value":20000,
"HOSTNAME":"stage-01",
"json_message":["{\"activeSessions\":0}"],
"tags":[]
}
I tried to parse the incoming JSON using a simple JSON filter. See here my configuration:
input {
lumberjack {
<snipped>
codec => "json"
}
}
filter {
json {
source => "json_message"
}
}
output {
elasticsearch {
<snipped>
}
}
However this leads to following error in the logstash log. The JSON string in an array simply can't be handled.
{:timestamp=>"2014-03-25T19:43:13.232000+0100",
:message=>"Trouble parsing json",
:source=>"json_message",
:raw=>["{\"activeSessions\":0}"],
:exception=>#<TypeError: can't convert Array into String>,
:level=>:warn}
Is there a way to extract the JSON string from the array prior to parsing? Any help is greatly appreciated. Thanks.
Actually, it is quite simple and plays along the lines of common programming languages. Though, I did not find the answer in the docs.
Just add an index to the field in the filter:
filter {
json {
source => "json_message[0]"
}
}

What are the best practices to add metadata to a RESTful JSON response?

Background
We are building a Restful API that should return data objects as JSON. In most of the cases it fine just to return the data object, but in some cases, f.ex. pagination or validation, we need to add some metadata to the response.
What we have so far
We have wrapped all json responses like this example:
{
"metadata" :{
"status": 200|500,
"msg": "Some message here",
"next": "http://api.domain.com/users/10/20"
...
},
"data" :{
"id": 1001,
"name": "Bob"
}
}
Pros
We can add helpful metadata to the response
Cons
In most cases we don't need the metadata field, and it adds complexity to the json format
Since it's not a data object any more, but more like a enveloped response, we can not use the response right away in f.ex backbone.js without extracting the data object.
Question
What is the best practices to add metadata to a json response?
UPDATE
What I've got so far from answers below:
Remove the metadata.status an return the http response code in the
http protocol instead (200, 500 ...)
Add error msg to body of an http 500 repsonse
For pagination i natural to have some metadata telling about the pagination structure, and the data nested in that structure
Small amount of meta data can be added to http header (X-something)
You have several means to pass metadata in a RESTful API:
Http Status Code
Headers
Response Body
For the metadata.status, use the Http Status Code, that's what's for!
If metadata is refers to the whole response you could add it as header fields.
If metadata refers only to part of the response, you will have to embed the metadata as part of the object.DON'T wrap the whole response in an artifical envelope and split the wrapper in data and metadata.
And finally, be consistent across your API with the choices you make.
A good example is a GET on a whole collection with pagination. GET /items
You could return the collection size, and current page in custom headers. And pagination links in standard Link Header:
Link: <https://api.mydomain.com/v1/items?limit=25&offset=25>; rel=next
The problem with this approach is when you need to add metadata referencing specific elements in the response. In that case just embed it in the object itself. And to have a consistent approach...add always all metadata to response. So coming back to the GET /items, imagine that each item has created and updated metadata:
{
items:[
{
"id":"w67e87898dnkwu4752igd",
"message" : "some content",
"_created": "2014-02-14T10:07:39.574Z",
"_updated": "2014-02-14T10:07:39.574Z"
},
......
{
"id":"asjdfiu3748hiuqdh",
"message" : "some other content",
"_created": "2014-02-14T10:07:39.574Z",
"_updated": "2014-02-14T10:07:39.574Z"
}
],
"_total" :133,
"_links" :[
{
"next" :{
href : "https://api.mydomain.com/v1/items?limit=25&offset=25"
}
]
}
Note that a collection response is an special case. If you add metadata to a collection, the collection can no longer be returned as an array, it must be an object with an array in it. Why an object? because you want to add some metadata attributes.
Compare with the metadata in the individual items. Nothing close to wrapping the entity. You just add some attributes to the resource.
One convention is to differentiate control or metadata fields. You could prefix those fields with an underscore.
Along the lines of #Charlie's comment: for the pagination part of your question you still need to bake the metadata into the response somhow, but the status and message attributes here are somewhat redundant, since they are already covered by the HTTP protocol itself (status 200 - model found, 404 - model not found, 403 - insufficient privs, you get the idea) (see spec). Even if your server returns an error condition you can still send the message part as the response body. These two fields will cover quite much of your metadata needs.
Personally, I have tended towards (ab)using custom HTTP headers for smaller pieces of metadata (with an X- prefix), but I guess the limit where that gets unpractical is pretty low.
I've expanded a bit about this in a question with a smaller scope, but I think the points are still valid for this question.
I suggest you to read this page https://www.odata.org/ You are not forced to use OData but the way they do the work is a good example of good practice with REST.
We had the same use case, in which we needed to add pagination metadata to a JSON response. We ended up creating a collection type in Backbone that could handle this data, and a lightweight wrapper on the Rails side. This example just adds the meta data to the collection object for reference by the view.
So we created a Backbone Collection class something like this
// Example response:
// { num_pages: 4, limit_value: 25, current_page: 1, total_count: 97
// records: [{...}, {...}] }
PageableCollection = Backbone.Collection.extend({
parse: function(resp, xhr) {
this.numPages = resp.num_pages;
this.limitValue = resp.limit_value;
this.currentPage = resp.current_page;
this.totalCount = resp.total_count;
return resp.records;
}
});
And then we created this simple class on the Rails side, to emit the meta data when paginated with Kaminari
class PageableCollection
def initialize (collection)
#collection = collection
end
def as_json(opts = {})
{
:num_pages => #collection.num_pages
:limit_value => #collection.limit_value
:current_page => #collection.current_page,
:total_count => #collection.total_count
:records => #collection.to_a.as_json(opts)
}
end
end
You use it in a controller like this
class ThingsController < ApplicationController
def index
#things = Thing.all.page params[:page]
render :json => PageableCollection.new(#things)
end
end
Enjoy. Hope you find it useful.
How about returning directly the object that you want in data, like return:
{
"id": 1001,
"name": "Bob"
}
And return in headers the metadata.
Option 1 (one header for all metadata JSON):
X-METADATA = '{"status": 200|500,"msg": "Some message here","next": "http://api.domain.com/users/10/20"...}'
Option 2 (one header per each metadata field):
X-METADATA-STATUS = 200|500
X-METADATA-MSG = "Some message here",
X-METADATA-NEXT = "http://api.domain.com/users/10/20"
...
Until now I was using like you, a complex JSON with two fields, one for data and one for metadata. But I'm thinking in starting using this way that I suggested, I think it will be more easy.
Remind that some server have size limit for HTTP headers, like this example: https://www.tutorialspoint.com/What-is-the-maximum-size-of-HTTP-header-values
JSON:API solves this by defining top-level meta and data properties.

Categories

Resources