Json null data behaving strangely - json

I am using grails 2.3.3 in a development and I'm having a problem working with a 2 dimensional array that has been taken from a json web page. The particular problem occurs when there are null values in 3rd column of the 2D array.
Here is an overview of the workflow in grails:
The json object is first rendered:
render ( ['P' : jsonObject.picId, 'A' : jsonObject.audioId, 'C' : jsonObject.caption, 'V' : jsonObject.vidTemplateId ] as JSON)
It is then recast into a 2D array to pass in a storeVideoSlotData service:
def vidpNmList = [][]
vidpNmList[0] = jsonObject.picId
vidpNmList[1] = jsonObject.audioId
vidpNmList[2] = jsonObject.caption
Then a call to the service which passes vidpNmList:
def vsaInst = vdSlotService.storeVideoSlotData( vidpNmList, session)
Within the service it gets recast again into it's three separate components:
def picId = vidpNmList[0]
def audioId = vidpNmList[1]
def caption = vidpNmList[2]
Here is a listing of the two forms of the data:
vidpNmList: [[331, 332, 334, null, null, null, null, null, null, null, null, null], [null, null, null, null, null, null, null, null, null, null, null, null], [null, Input Caption Data, Input Caption Data, null, null, null, null, null, null, null, null]]
picId: [331, 332, 334, null, null, null, null, null, null, null, null, null]
audioId:[null, null, null, null, null, null, null, null, null, null, null, null]
Captions: [null, Input Caption Data, Input Caption Data, null, null, null, null, null, null, null, null]
Within this service any reference to specific values in this caption column that contain null values causes an error:
When caption[currSlotNo] has a null value this line causes an error:
if(!(caption[currSlotNo]) ) {
log.debug(" caption is null and cannot be displayed. ")
}
The error being:
homevu1.VdSlotService updVideoSlotData pictureInst : 331 picId[currSlotNo]: 331
homevu1.VdSlotService updVideoSlotData picMK: 331
homevu1.VdSlotService updVideoSlotData audMK: null
errors.GrailsExceptionResolver JSONException occurred when processing request: [POST] /HomeVu1/videoShr/getJsVidCoords
JSONArray[0] not found.. Stacktrace follows:
org.codehaus.groovy.grails.web.json.JSONException: JSONArray[0] not found.
The same error occurs if I refer to the value of the element within the vidpNmList array.
What am I doing wrong or perhaps there is some work around?
Here is a workaround I've introduced with a 'try/catch' construct whcih leaves the 'captionVal' as null:
def captionVal = null
try{ captionVal = caption[currSlotNo]
log.debug(" ${functionName} caption value assigned correctly ")
}
catch (Exception eWrite)
{
// fails - can only trap and work around the error atm.
log.debug(" ${functionName} caption value fails to assign correctly - remains at null default - Error Message: $eWrite")
}
Code showing resetting the json object caption element from a "null" string to an actual null prior to assigning it to vidpNmList:
for (def iC = 0; iC < jsonObject.caption.size() ; iC++)
{
String currCap = jsonObject.caption[iC]
if( currCap == "null")
{
log.debug(" getJsVisCoords null value iC: $iC " + " caption[iC]: " + jsonObject.caption[iC] + " currCap Length: " + currCap.length())
jsonObject.caption[iC] = null
}
else
{
log.debug(" getJsVisCoords Non null value iC: $iC " + " caption[iC]: " + jsonObject.caption[iC] + " currCap Length: " + currCap.length())
}
}
vidpNmList[2] = jsonObject.caption
-mike

Unsure where the JSON gets involved in this scenario but looking at you code above you have other choices:
Up to where you have these Lists collected as caption audioId picId
def picId = vidpNmList[0]
def audioId = vidpNmList[1]
def caption = vidpNmList[2]
You showed an output closed to this:
def picId=[331, 332, 334, null, null, null, null, null, null, null, null, null]
def audioId=[null, null, null, null, null, null, null, null, null, null, null, null]
def Captions=[null, 333, 333, null, null, null, null, null, null, null, null]
Now this is me playing around with the list:
/ you are current failing on this
def pic=picId[0]
//instead of above element[id] try .get(id)
def cap=Captions.get(2)
println "--- ${pic} ### ${cap}"
//Then you can test by saying
if (cap&&something&&somethingEls) {
doSomething
}
I get back
--- 331 ### 333
Anyways to find out more above lists If that is what you are getting back in those objects have a look here Take a look here: http://mrhaki.blogspot.co.uk/2009/10/groovy-goodness-finding-data-in.html
Edited to add in regards to the for loop:
for (def iC = 0; iC < jsonObject.caption.size() ; iC++)
Typically in groovy the for loop should be expressed like this:
int iC=0
for (iC < jsonObject.caption.size() ; iC++) {
Anyways try this:
jsonObject?.caption?.eachWithIndex{ item, i ->
if (JSONObject.NULL.equals(item) {
item=null
}
}
vidpNmList[2] = jsonObject.caption
If that fails you could try iterating it to a new list although I doubt it will really be required:
def finalList=[]
jsonObject?.caption?.eachWithIndex{ item, i ->
if (JSONObject.NULL.equals(item) {
item=null
}
finalList << item
}
vidpNmList[2] = finalList
much shorter and easier to follow than your for loop version :) I added withIndex and i and in your case if be item[i] but there is no need since you are already iterating through each element so you could even cut it down further to :
jsonObject?.caption?.each{ item ->
if (JSONObject.NULL.equals(item) {
item=null
}
}
vidpNmList[2] = jsonObject.caption
You may need to tweak this if (JSONObject.NULL.equals(item) { in all of the above examples since thinking about it, this is no longer json so to something like this:
if (!item ||(item && item=='null')) {
item=null
}

Related

How to import backend exported public key in frontend

hi i'm trying to import a jwk generated from the server in my flutter app
var signeature =
JsonWebSignature.fromCompactSerialization(response.body);
var payload = signeature.unverifiedPayload;
Map<String, dynamic> key = jsonDecode(payload.jsonContent["jwk"]);
PublicKey rsakey = RsaPublicKey(e: key['e'], n: key['n']);
Jwk jwk = Jwk.fromPublicKey(rsakey);
the problem is that RsaPublicKey requires e and n as List<int> but my keys has no List<int>
{additionalData: {}, alg: null, crv: null, d: null, dp: null, dq: null, e: AQAB, k: null, keyId: null, keyOps: [], kid: null, kty: RSA, n: rnuxgDk-9cWCeehBWotGz2YkXpu6_0wPVlVkip1EHUdpWXpX4vAvOeclNIrEYzMOrBIUvwLptk-FMsOgpdvxjWtHFfanv60xsTLAV6ZXMO-R2Ojzgpv4izFvyduC2MihkoMBL_evo9JltMfX2ZSXIwwZoqPed2v9GI9aIjhhKZqju-anVjt3n6dHxlLyduaoatZbD7tzjo-bPeO8o1rycBQFCncgdQ9ST3C6CmZYOUpCFF9ojb4vZtvmIcbtl9Hyud9dOViufE1vPrpJq0ZjeR_ovtApfaQKsi3YJhn77Uwg_XxzgE-SPq960skNwd0IFpyiuxcOvRRIvL6N_-FCdw, oth: null, p: null, q: null, qi: null, use: null, x: null, x5c: [], x5t: null, x5tS256: null, x5u: null, y: null, keySize: 2048, hasPrivateKey: false, cryptoProviderFactory: {cryptoProviderCache: {}, customCryptoProvider: null, cacheSignatureProviders: true, signatureProviderObjectPoolCacheSize: 4}}
is it possible to convert e and n into a List<int>?
I tried using other defined PublicKey but on the import it asks for bigint instead of list but i still don't know how to convert it into bigint anyway

How to get the YEAR of the created_at column inside the table using LARAVEL

I'm trying to create a query that display all the driver's information and only get the "Year" in created_at column. Can anyone help me? thanks in advance
Here's the response query
"user_id": 45,
"driver_fname": "Sample",
"driver_mname": "Sample",
"driver_lname": "Sample",
"driver_birthday": "2000-07-28",
"years_driving_experience": null,
"years_driving_experience_quicktrans": null,
"start_year_of_exp_in_driving": null,
"start_year_of_exp_in_driving_in_quicktrans": null,
"educational_attainment": null,
"health_status": null,
"drug_test": null,
"marital_status": null,
"Salary_range": null,
"license_registration": null,
"license_expiration": null,
"license_condition": null,
"medication_maintenance": null,
"training": null,
"driver_height": null,
"driver_weight": null,
"weight_status": null,
"emergency_contact_number": null,
"home_address_street_number": null,
"home_address_street": null,
"home_address_brgy": null,
"home_address_city": null,
"work_hours_range": null,
"work_shift": null,
"sleep_hours_range": null,
"smoker": null,
"created_at": "2021-11-23 03:50:33"
the created_at column should be in Year, for example created_at:"2021"
Here is my query code
$driversInformation = DriverInformation::all(['user_id','driver_fname','driver_mname','driver_lname',
'driver_birthday','years_driving_experience','years_driving_experience_quicktrans','start_year_of_exp_in_driving',
'start_year_of_exp_in_driving_in_quicktrans','educational_attainment','health_status','drug_test','marital_status',
'salary_level As Salary_range','license_registration','license_expiration','license_condition','medication_maintenance',
'training','driver_height','driver_weight','weight_status','emergency_contact_number','home_address_street_number',
'home_address_street','home_address_brgy','home_address_city','work_hours_range','work_shift','sleep_hours_range','smoker',
'created_at As year']);
The easiest way is to mutate the date in your DriverInformation model
/**
* The attributes that should be cast.
*
* #var array
*/
protected $casts = [
'created_at' => 'datetime:Y',
];
You can read more about mutators here https://laravel.com/docs/8.x/eloquent-mutators#date-casting
SQL Query should be
select Year(createdAt) as Year from Persons;
you can check the example here https://www.db-fiddle.com/f/d5j8icfiw8nvwZdKqhtr4h/0
You can use Carbon class ->
\Carbon\Carbon::parse($item->created_at)->format('Y')

How to decode LONGTEXT/TEXT type in swift

anyone know how to decode a mysql 'LONGTEXT' or 'TEXT' type in swift?
I'm using nodejs get data from mysql and expose it as REST API, and call the API from my swift code. the problem is swift can't decode 'background' and 'notes', it's working if i remove these two columns from the Vote struct
The database table 'vote', the structure is like :
CREATE TABLE `vote` (
`createdAt` bigint(20) DEFAULT NULL,
`updatedAt` bigint(20) DEFAULT NULL,
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`thumbnail` varchar(255) DEFAULT NULL,
`background` longtext DEFAULT NULL,
`notes` text,
`amount` double DEFAULT NULL,
`type` varchar(255) DEFAULT NULL,
`highestScore` double DEFAULT NULL,
`category` int(11) DEFAULT NULL,
`user` int(11) DEFAULT NULL,
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;
the json format is like
[{
"id": 1,
"name": "IQ Test",
"thumbnail": "eddie",
"background": "This is a typical IQ test",
"amount": 33,
"type": "score",
"highestScore": 174
}]
my code in swift is:
struct Vote: Codable {
var id: Int
var name: String
var thumbnail: String
var background: String
var notes: String
var amount: Double
var type: String
var highestScore: Double
enum CodingKeys: String, CodingKey {
case id
case name
case thumbnail
case background
case notes
case amount
case type
case highestScore
}
}
the decode piece is like:
if let data = data {
if let votes = try? jsonDecoder.decode([Vote].self, from: data) {
completion(votes)
}
} else {
completion(nil)
}
Hey Danny, I have run your code and get an optimized way as follows:-
Construct the model structure like this:-
// MARK: - CourseElement
struct VoteElement: Codable {
let id: Int?
let name, thumbnail, background: String?
let amount: Int?
let type: String?
let highestScore: Int?
}
typealias Vote = [VoteElement]
Use the above structure in the network calls like this:-
if let data = data {
if let votes = try? jsonDecoder.decode(Vote.self, from: data) {
completion(votes)
}
} else {
completion(nil)
}

How do I POST multiple JSON objects

I would like to know how to go about posting multiple JSON objects to the server using django-restframework. My datatable model is given below.
class module(models.Model):
uploaded_by=models.ForeignKey(ChangeLog,on_delete=models.CASCADE,null=True)
panel_manufacturer= models.CharField(max_length=100,null=True, blank = True)
panel_model= models.CharField(max_length=100,null=True, blank = True)
panel_serial_number = models.CharField(max_length=100)
label_pmpp=models.FloatField(null=True, blank = True)
label_lower_tolerance=models.FloatField(null=True, blank = True)
label_upper_tolerance=models.FloatField(null=True, blank = True)
label_isc=models.FloatField(null=True, blank = True)
label_voc=models.FloatField(null=True, blank = True)
label_maximum_system_voltage=models.FloatField(null=True, blank = True)
additional_panel_information = JSONField(null=True, blank = True)
def __str__(self):
return self.panel_serial_number
And the corresponding serializer is as such
class module_Serializer(serializers.HyperlinkedModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name="pvlabs_testdata:module-detail")
uploaded_by = ChangeLog_Serializer(required=False)
class Meta:
model = module
fields = '__all__'
validators = [module_validator]
def create(self, validated_data):
uploaded_by_data = {"uploaded_by":self.context['request'].user, "upload_timestamp":datetime.now()}
uploaded_by_instance = ChangeLog.objects.create(**uploaded_by_data)
module_instance=module.objects.create(uploaded_by=uploaded_by_instance, **validated_data)
return module_instance
When I go about posting a JSON like below
{
"panel_manufacturer": "XYZ",
"panel_model": null,
"panel_serial_number": "EFG",
"label_pmpp": null,
"label_lower_tolerance": null,
"label_upper_tolerance": null,
"label_isc": null,
"label_voc": null,
"label_maximum_system_voltage": null,
"additional_panel_information": null
},
{
"panel_manufacturer": "XYZ",
"panel_model": null,
"panel_serial_number": "ABC",
"label_pmpp": null,
"label_lower_tolerance": null,
"label_upper_tolerance": null,
"label_isc": null,
"label_voc": null,
"label_maximum_system_voltage": null,
"additional_panel_information": null
},
{
"panel_manufacturer": "XYZ",
"panel_model": null,
"panel_serial_number": "ABC",
"label_pmpp": null,
"label_lower_tolerance": null,
"label_upper_tolerance": null,
"label_isc": null,
"label_voc": null,
"label_maximum_system_voltage": null,
"additional_panel_information": null
}
I always get an error that says 'Expected dict, got list'.
I managed to create a solution for this using list serializer.
So in my views file, it is coded as below
class module_ViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows groups to be viewed or edited.
"""
queryset = module.objects.all()
serializer_class = module_Serializer
permission_classes = [permissions.IsAuthenticated | HasAPIKey]
def get_serializer(self, *args, **kwargs):
if isinstance(kwargs.get("data", {}), list):
kwargs["many"] = True
temp= kwargs.get("data")
for i in range(len(kwargs.get("data"))):
for key, value in temp[i].items():
if " " in key or key.islower()==0:
n_key=str(key).replace(" ", "_").title().lower()
kwargs.get("data")[i][n_key] = kwargs.get("data")[i].pop(key)
return super(module_ViewSet, self).get_serializer(*args, **kwargs)
And for my serializer I have coded as below
from rest_framework import serializers
from django_restql.mixins import DynamicFieldsMixin
class BulkModuleSerializer(DynamicFieldsMixin, serializers.ListSerializer):
def create(self, validated_data):
result=[]
for validated_datas in validated_data:
uploaded_by_data = {"uploaded_by":self.context['request'].user, "upload_timestamp":datetime.now()}
uploaded_by_instance = ChangeLog.objects.create(**uploaded_by_data)
module_instance=module.objects.create(uploaded_by=uploaded_by_instance, **validated_datas)
result.append(module_instance)
return result
class module_Serializer(DynamicFieldsMixin, serializers.HyperlinkedModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name="pvlabs_testdata:module-detail")
uploaded_by = ChangeLog_Serializer(required=False)
class Meta:
model = module
fields = '__all__'
validators = [module_validator]
list_serializer_class = BulkModuleSerializer
def create(self, validated_data):
uploaded_by_data = {"uploaded_by":self.context['request'].user, "upload_timestamp":datetime.now()}
uploaded_by_instance = ChangeLog.objects.create(**uploaded_by_data)
module_instance=module.objects.create(uploaded_by=uploaded_by_instance, **validated_data)
return module_instance
That seems to have worked for me.
You have put your JSON data inside square brackets.
Example:
[
{
"panel_manufacturer": "XYZ",
"panel_model": null,
"panel_serial_number": "ABC",
"label_pmpp": null,
"label_lower_tolerance": null,
"label_upper_tolerance": null,
"label_isc": null,
"label_voc": null,
"label_maximum_system_voltage": null,
"additional_panel_information": null
},
{
"panel_manufacturer": "XYZ",
"panel_model": null,
"panel_serial_number": "ABC",
"label_pmpp": null,
"label_lower_tolerance": null,
"label_upper_tolerance": null,
"label_isc": null,
"label_voc": null,
"label_maximum_system_voltage": null,
"additional_panel_information": null
}
]

Parse the result of a mysql select query on multiple tables with nodeJS

I'm a nodeJS beginner and am trying to learn it by creating a blog. To do so, I have three tables
CREATE TABLE `articles` (
`article_id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(255) NOT NULL,
`content` longtext NOT NULL,
`image` varchar(255) NOT NULL,
`created` datetime NOT NULL,
`author_id` int(11) NOT NULL,
PRIMARY KEY (`article_id`)
)
CREATE TABLE `authors` (
`author_id` int(11) NOT NULL AUTO_INCREMENT,
`email` varchar(255) NOT NULL,
PRIMARY KEY (`author_id`)
)
CREATE TABLE `comments` (
`comment_id` int(11) NOT NULL AUTO_INCREMENT,
`comment_content` longtext NOT NULL,
`created` datetime NOT NULL,
`comment_author` varchar(255) NOT NULL,
`id_article` int(11) NOT NULL,
PRIMARY KEY (`comment_id`)
)
On my page, I want to get all my articles, with their associated authors and comments.
This is my node code to get the data :
app.get('/api/articles', function(req, res){
connection.query('SELECT * FROM articles LEFT JOIN authors ON articles.author_id = authors.author_id LEFT JOIN comments ON articles.article_id = comments.id_article', function(err, row, fields){
if(!err){
res.json(rows);
}else
console.log('Error');
});
});
This query returns the data I need, but I want to parse it to get something that I can use easier in the front part, like
[
{
article_id: 1,
content: 'test',
title: 'test',
image: '',
author: {
author_id: 1,
email: 'test#test.com'
},
comments: [
{
comment_id: 1,
comment_content: 'test',
comment_author: 'test'
},
{
comment_id: 2,
comment_content: 'test',
comment_author: 'test'
}
]
}
]
Instead of the current return that looks like
[
{
article_id: 1,
title: 'test',
content: 'test',
image: '',
author_id: 1,
email: 'test#test.com',
comment_id: 1,
comment_content: 'test',
comment_author: 'test
}
]
I spent some time looking for something to do it, but couldn't find anything, so if someone knows how to do it, I'd be very grateful.
Thanks
You'll need to do two things:
(1) make sure you are sorting by article_id in your query
(2) create a tiny state machine, keeping track of the article_id, and loop through each record aggregating the comments. if your article_id changes, write the record to the table and move on to the next article:
var table = [];
var lastid = -1;
var article = {};
for(var i=0;i<rows.length;i++) {
var row = rows[i];
if (row.article_id!==lastid) {
//The id has changed, so create a new article
if (article.article_id) {
//If this isnt the first time looping, add the last article to the table
table.push(article);
}
article = {};
//create the structure you want
article.article_id = row.article_id;
article.title = row.title,
article.content = row.content,
article.image = row.image,
article.author = {
author_id: row.author_id,
email: row.email,
};
//comments go in this array. add the first one
article.comments = [{
comment_id:row.comment_id,
comment_content:row.commment_content,
comment_author:row.comment_author
}];
} else {
//same article, new comment
article.comments.push({
comment_id:row.comment_id,
comment_content:row.commment_content,
comment_author:row.comment_author
})
}
//update the id to check against the next row
lastid = row.article_id;
}
//make sure you push on the last article
table.push(article);
//Now you can send back the table in the new structure...
return table;