Django serializers - add/update fields attribute value - json

I'm using Django serializer for serializing the model data into JSON.
For example:- I have a model(CHECKTYPE) that contains one field 'types'.
Now 'types' contains comma(,) separated items like 'test, test1, test2'.
I'm using Django serializer like below (somewhere in view.py):
gettypes = CHECKTYPE.objects.all()
mytypes = serializers.serialize("json", gettypes)
return HttpResponse(mytypes, content_type="application/json")
This returns me a JSON on web page like below:
[{"model": "porttype.CHECKTYPE", "pk": "xyz00000005", "fields": {"types": "test, test1, test2"}}]
Now here I want to manipulate the fields attributes before serializing the data.
For example: I want to add one more attribute in fields 'lasttype' which will be last index of the list if I split the 'types' by comma.
lasttype = types.split(',')[-1]
so final json response should look like this:
[{"model": "porttype.CHECKTYPE", "pk": "xyz00000005", "fields": {"types": "test, test1, test2", "lasttype":"test2"}}]
I tried to do this like below but it's not working:
gettypes = CHECKTYPE.objects.all()
updated_types = []
for mtype in gettypes:
mtype.lasttype = mtype.types.split(',')[-1]
updated_types.append(mtype)
mytypes = serializers.serialize("json", updated_types)
return HttpResponse(mytypes, content_type="application/json")
But this is not working. It's giving me same JSON response and not showing the 'lasttype' attribute.
Please let me know if there is any possibility to achieve this.
Thanks,
Shashank

The best way to modify the response you are sending is by loading the json to dict then modifying the dict, then again json dumps the data for the response.

Instead of modifying fields before serializing, you should modify the fields after serializing.
import json
mytypes = json.loads(serializers.serialize("json", gettypes))
updated_types = []
for mytype in mytypes:
last_type = mytype['fields']['types'].split(',')[-1]
mytype['fields']['lasttype'] = last_type
updated_types.append(mytype)
return JsonResponse(updated_types)
By using JsonResponse you can directly json data without re-serializing the dict or list.
The expected data should be like this:
'[{"pk": "xyz00000005", "model": "porttype.CHECKTYPE", "fields": {"lasttype": " test2", "types": "test, test1, test2"}}]'

Related

Groovy parse Json preserve keys order

I try to parse a Json in groovy/Jenkins(I have no access to readJSON step) and keep the json keys order.
After my research, I found that groovy Map/HashMap objects are not preserving the order of the keys.
The only type which keeping order is LinkedHashMap So I try to convert the output of JsonSlurper.parseText to linkedhashmap but it still changing the items order
def jsonstr = """
{
"Id": 533,
"StartTime": "2022-05-10 11:56:18",
"EndTime": "2022-05-10 11:58:49",
"TimeShift": "N/A",
"Run": "123",
"Setup": "Test",
"Version": "3.17",
"Result": "pass",
"DebugMode": 1,
"NumberOfCores": 3,
}
"""
//init as LinkedHashMap
LinkedHashMap map = new LinkedHashMap()
map = (LinkedHashMap) (new JsonSlurperClassic().parseText(jsonstr))
println(map)
/*
the output is in incorrect order, I expect to get `Id` attribute as a first key but I'm getting:
[EndTime:2022-05-10 11:58:49, Version:3.17, TimeShift:N/A, StartTime:2022-05-10 11:56:18, DebugMode:1, Run:123, NumberOfCores:3, Id:533, Setup:Test, Result:pass]
*/
Here is the solution:
I realized that readJSON step is keeping the order so I try to take a look at its implementation.
readJSON uses net.sf.json.* library, in this library there is an option to parse string to jsonObject (with keeping the order of the keys!) by:
import net.sf.json.JSONSerializer
def map = JSONSerializer.toJSON(jsonstr)
println(map)
NOTES:
if you want use it during a pipeline I suggest you to use readJSON step itself, otherwise, you'll need to approve this function from Manage Jenkins -> script approval
In this method empty properties will be net.sf.json.JSONNull
which holds a textual value "null" -> if (someEmptyKey != null) always returns true (also when null) to avoid that, use:
if (!someEmptyKey instanceof JSONNull )
Sources: docs, jenkins-implementation

How to filter a complex response in karate dsl using jsonPath?

I am getting below response from a REST API, but I am finding it difficult to extract label value from the received response and assign it to a variable to use it later in script.
Here is the RESPONSE::
{
"result": "SUCCESS",
"rawAttr": "[{\"attributes\":[{\"name\":\"resourceid\",\"value\":\"7A7Q123456\"},{\"name\":\"physicalid\",\"value\":\"7A7Q123456\"},{\"name\":\"dsw:label\",\"value\":\"MY Product00004285\"},{\"name\":\"dsw:created\",\"value\":\"2019-11-06T08:39:39Z\"}]}]",
"physicalid": "7A7Q123456",
"contextPath": "/path",
"id": "7A7Q123456",
"message": null
}
I am able to get response.id and response.result which is helpful for validation but I am not able to get the dsw:label value which is MY Product00004285
When I do def Arr = response.rawAttr I get the below value whether it is Array or String I am confused. Seems like it is a string.
[{"attributes":[{"name":"resourceid","value":"7A7Q123456"},{"name":"physicalid","value":"7A7Q123456"},{"name":"dsw:label","value":"MY Product00004298"},{"name":"dsw:created","value":"2019-11-06T08:39:39Z"}]}]
It is very easy to extract the label in JMeter JSON Extractor using below JSON Path expression
$.attributes.value[2]
Refer Karate's type conversion capabilities: https://github.com/intuit/karate#type-conversion
So you can do this:
* json attr = response.rawAttr
And then you are all set.
Thanks to an example and documentation on converting string to json.
Got it how to do.
And def strVar = response.rawAttr
And json jsonVar = strVar
And def attrb = karate.jsonPath(jsonVar, '$..attributes.[2].value')[0]
And print '\n\n Attrb\n', attrb
Links I referred:
Json Path evaluator
Karate doc reference for type conversion
Karate example for type-conversion

Decode resulting json and save into db - Django + Postgres

I have a model like this:
class MyClass(models.Model):
typea = models.CharField(max_length=128)
typeb = models.CharField(max_length=128)
If for example, the resulting json from an API is like this:
{
"count": 75,
"results": [
{
"typea": "This tipe",
"typeb": "A B type",
"jetsons": [],
"data": [
"https://myurl.com/api/data/2/",
],
"created": "2014-12-15T12:31:42.547000Z",
"edited": "2017-04-19T10:56:06.685592Z",
},
I need to parse this result and save typea and typeb into the database, I'm kind of confused on how to do this.
I mean, there is the JSONField on Django, but I don't think that will work for me, since I need to save some specific nested string of the json dict.
Any example or idea on how to achieve this?
I mean, my confusion is on how to parse this and "extract" the data I need for my specific fields.
Thank You
You can always do an import json and use json.load(json_file_handle) to create a dictionary and extract the values you need. All you need is to open the .json file (you can use with open("file.json", "r") as json_file_handle) and load the data.

How to validate entire JSON with 1 dynamic field with JMeter

I have a JSR223 Assertion in JMeter that validates entire JSON response and its working.
The problem is that each time I insert data in DB one of JSON fields changes and validation fails.
How could I skip that dynamic field from response validation?
Response JSON example:
[
{
"id": "273444",
"trxDateTime": "2019-03-25T22:38:16Z",
"merchantName": "MerchECOM1",
"merchantTransId": "1r1vXue4qn",
"trxType": "Payment",
"paymentBrand": "MasterCard",
"amount": 20.00,
"currencyCode": "AUD",
"status": "Declined",
"statusResponseMessage": null,
"customerAccount": "123456"
}
]
JSR223 Assertion:
def expected = new groovy.json.JsonSlurper().parseText(vars.get('expected1'))
def actual = new groovy.json.JsonSlurper().parse(prev.getResponseData())
if (expected != actual) {
AssertionResult.setFailure(true)
AssertionResult.setFailureMessage('Mismatch between expected and actual JSON')
}
just with this I'm not able to validate the dynamic "id" field
any idea?
Thanks in advance
If you're not interested in this id field - just remove it from the expected variable and the actual response, to wit amend first 2 lines of your assertion to look like:
def expected = new groovy.json.JsonSlurper().parseText(vars.get('expected1')).each {entry -> entry.remove('id')}
def actual = new groovy.json.JsonSlurper().parse(prev.getResponseData()).each {entry -> entry.remove('id')}
More information:
Groovy: Parsing and Producing JSON
Apache Groovy - Why and How You Should Use It
Demo:
If value is not your concern for id field you can directly use regex matcher to check the field using Jsonassertion by specifying jsonpath and check match as regex use regex

Extract list of fields from Nested Json using Json4s Scala

I am trying to parse the nested Json and get the list of name from the fields tag.
{
"subject": "table-name",
"version": 1,
"id": 234,
"schema": "{
\"type\":\"record\",\"name\":\"table-name\",
\"fields\":[
{\"name\":\"NAME\",\"type\":\"CHARACTER\},
{\"name\":\"EID\",\"type\":\"INT\"},
{\"name\":\"DEPARTMENT\",\"type\":\"CHARACTER\"}
]
}"
}
I checked couple of post and came up with below code. I can get the schema definition(which is fairly easy) but not able to the list of name from fields.
case class Names(name : String)
case class FieldNames(fields: List[Names])
case class ColNames(subject: String, schema: FieldNames)
implicit val formats = DefaultFormats
val sourceSchema = parse("JsonStr").extract[ColNames]
println(sourceSchema)
My idea was the part schema: FieldNames will get me the fields tag and then List[Names] will get me the list of name but all I get is empty list. If I change the schema: FieldNames with schema: String I get the schema too but I am not getting how to get the required list of name after that. Below is the current output:
ColNames(table-name,FieldNames(List()))
Update:
I got it working but I ended up parsing the same Json twice which I don't feel is a best way of doing it. I would still like to know the best way to get it done. Below is my current solution:
case class Name(name : String)
case class FieldNames(fields: List[Name])
case class ColNames(subject: String, schema: String)
val sourceSchema = parse("JsonStr").extract[ColNames]
val cols= parse(sourceSchema.schema).extract[FieldNames]
Output:
FieldNames(List(Name(NAME), Name(EID), Name(DEPARTMENT)))