deleting a dictionary record in a SwiftyJSON array - ios

Swift 3.0 iOS 10.x SwiftyJSON
I have a SwiftyJSON array of dictionary objects that looks like this ...
[
{
"figure" : 1326,
"account" : "Charles"
}
{
"figure" : 2361,
"account" : "James"
}
]
I want to delete the record within it belonging to "James", and I came up with this code. jsonObjects contains the array you see above.
var json2S = sharedDataAccess.jsonObjects
for json2DX in 0..<json2S.count {
var delIndex: Int? = nil
for (jsonK, subJson) in sharedDataAccess.jsonObjects[json2DX] {
print("json2D \(jsonK) \(subJson.stringValue) \(Name)")
if jsonK == "account" && subJson.stringValue != Name {
delIndex = json2DX
print("DELETE IT \(jsonK) \(subJson.stringValue) \(Name)")
}
}
if delIndex != nil {
json2S[0].arrayObject?.remove(at: delIndex!)
print("DELETING IT \(delIndex) \(Name)")
}
}
sharedDataAccess.jsonObjects = JSON(json2S)
It works, but not quite the way I had hoped. It deletes James [assuming Name variable contains James], but it leaves me with this.
[
null,
{
"figure" : 1326,
"account" : "Charles"
}
]
James is replaced with null... A null I don't want, how can I delete entries but not get a null or indeed just delete the null too!!

Ok, here is my answer. Posted it for good measure; not quite the same logic but followed Vadian's point.
var json2S = sharedDataAccess.jsonObjects
var jsonA:[[String:Any]] = []
for json2P in sharedDataAccess.jsonObjects {
print("json2P \(json2P)")
var jsonDict:[String:Any] = [:]
var json2Save = false
for (jsonK, subJson) in json2P {
print("jsonK \(jsonK) \(subJson.stringValue) \(fnName)")
jsonDict[jsonK] = subJson.stringValue
if jsonK == "account" && subJson.stringValue == fnName {
json2Save = true
}
}
if json2Save {
jsonA.append(jsonDict)
}
}
let sharedDataAccess.jsonObjects = JSON(jsonA)

Related

Returning recursive result

I currently have this in a simple MVC Api controller:
var rootFolder = Umbraco.TypedMedia(200);
return rootFolder.Children().Select(s => new MediaItem
{
Name = s.Name,
Children = s.Children.Select(e => new MediaItem
{
Name = e.Name
})
});
It works, but only return level 1 and 2.
I tried using
return rootFolder.Descendants(), which returns all results from all levels - but "flattened out", so I cannot see the structure in the output.
The output is used in a simple app, navigating a tree structure.
Any ideas, as to how I can make it recursive?
Using Descendants, the output is returned like this
[
{
"Name":"dok1"
},
{
"Name":"dok2"
},
{
"Name":"dok21"
}
]
But it should be
[
{
"Name":"dok1"
},
{
"Name":"dok2"
"Children": [
{
"Name":"dok21"
}
]
}
Not sure you really need recursion here -- the solution below (or something similar) should suffice
// Dictionary between level/depth(int) and the files on that level/depth
var fileDictionary = new Dictionary<int, List<MediaItem>>();
var children = rootFolder.Children();
var depth = 1;
while (children.Any())
{
var tempList = new List<MediaItem>();
children.ForEach(child => {
tempList.Add(child);
});
fileDictionary.Add(depth, tempList);
children = children.Children();
depth++;
}
Then, you can do something like:
foreach (var key in fileDictionary.Keys)
{
// Access the key by key.Key (key would be "depth")
// Access the values by fileDictionary[key] (values would be list of MediaItem)
}
Why not just create a recursive function like so?
IEnumerable<MediaItem> ConvertToMediaItems(IEnumerable<IPublishedContent> items)
{
return items?.Select(i => new MediaItem
{
Name = i.Name,
Children = ConvertToMediaItems(i.Children)
}) ?? Enumerable.Empty<MediaItem>();
}
Then the usage would be
var rootFolder = Umbraco.TypedMedia(200);
return ConvertToMediaItems(rootFolder.Children());
You can also make the function a local function if it's only needed in one place.

How to create entry for 2 or more entity sets via OdataModel.create in UI5

I have a Odata service with 4 entity types - Address, CC, Header, Item, Comments.
After the user presses the "Order" button, I want to create an entry in backend using this service. There is a header and associated items that I need to pass.
oData Service from backend:
{
"d" : {
"__metadata" : {
"id" : "http://.../sap/opu/odata/sap/ZOrders/HeaderSet('3898')",
"uri" : "http://.../sap/opu/odata/sap/ZOrders/HeaderSet('3898')",
"type" : "ZOrder.Header"
},
"CompanyID" : "W",
"StockRoomID" : "A",
"SalesDocument" : "3898",
"ItemSet" : [
{
"__metadata" : {
"id" : "http://.../sap/opu/odata/sap/ZOrders/ItemSet(SalesDocument='3898',SalesDocumentItem='000010')",
"uri" : "http://.../sap/opu/odata/sap/ZOrders/ItemSet(SalesDocument='3898',SalesDocumentItem='000010')",
"type" : "ZOrders.Item"
},
"SalesDocument" : "3898",
"SalesDocumentItem" : "000010", //Line item number
"StockRoomID" : "A",
}
]
}
}
Controller.js
buttonClick: function(event) {
var sServiceURl = this.getOwnerComponent().getMetadata().getManifestEntry("sap.app").dataSources["ZOrders"].uri;
this.OdataModel = new sap.ui.model.odata.v2.ODataModel(sServiceURl);
var model = vc.getView().getModel();
var oEntry = {};
oEntry.CompanyID = model.getProperty("/CompanyID");
oEntry.StockRoomID = model.getProperty("/StockRoomID");
oEntry.SalesDocument = model.getProperty("/SalesDocument");
//Now want to pass items data to service so
//Creating an empty ItemSet array, pulling data from model.
//But my logic is wrong here for sure.
var itemData = [];
var itemsArray = v.getProperty("/ItemSet");
for (var i = 0; i < itemsArray.results.length; i++) {
itemData.push({
SalesDocument: itemsArray.results[i].SalesDocument,
SalesDocumentItem: itemsArray.results[i].SalesDocumentItem,
StockRoomID: itemsArray.results[i].StockRoomID,
});
}
oEntry.ItemSet = itemData;
this.OdataModel.create("/HeaderSet", oEntry, this._submitOrderSuccess.bind(this), this._submitOrderError.bind(this));
**Debugger - Header payload **
{
"CompanyID":"RSW0",
"StockRoomID":"A200",
"SalesDocument":"4053",
"Return":"X",
"Reason":"101",
"ItemSet":[
{
"SalesDocument":"4053",
"SalesDocumentItem":"000010",
"StockRoomID":"A200",
"ReturnItemFlag":"X",
"QtyToReturn":"1.000"
},
{
"SalesDocument":"4053",
"SalesDocumentItem":"000020",
"StockRoomID":"A200",
"ReturnItemFlag":"X",
"QtyToReturn":"1.000"
},
{
"SalesDocument":"4053",
"SalesDocumentItem":"000030",
"StockRoomID":"A200",
"ReturnItemFlag":"X",
"QtyToReturn":"1.000"
}
]
}
**Debugger - Response **
{
"d":{
"__metadata":{
"id":"https://.../sap/opu/odata/sap/ZORDER/HeaderSet('60000353')",
"uri":"https://.../sap/opu/odata/sap/ZORDER/HeaderSet('60000353')",
"type":"ZORDER.Header"
},
"CompanyID":"",
"StockRoomID":"",
"SalesDocument":"60000353",
"ReferenceDoc":"",
"AccountNumber":"",
"PoNumber":"",
"Message":"Return order 0060000353 has been created successfully",
"OrderTotal":"0.00",
"StockRoomName":"",
"Return":"",
"Reason":"",
"Auth":"",
"ItemSet":null,
"HeaderCSDSet":{
"__deferred":{
"uri":"https://.../sap/opu/odata/sap/ZORDER/HeaderSet('60000353')/HeaderCSDSet"
}
},
"AddressSet":{
"__deferred":{
"uri":"https://.../sap/opu/odata/sap/ZORDER/HeaderSet('60000353')/AddressSet"
}
},
"GeneralCommentsSet":{
"__deferred":{
"uri":"https://.../sap/opu/odata/sap/ZORDER/HeaderSet('60000353')/GeneralCommentsSet"
}
},
"CreditCardSet":{
"__deferred":"uri":"https://.../sap/opu/odata/sap/ZORDER/HeaderSet('60000353')/CreditCardSet"
}
}
}
}
This is a scenario of dependant Entity or Navigation property from Header to Item. Google "Deep Entity in SAPUI5 and oData for more understanding".
There is an error in your code where you have mentioned: "the logic is wrong".
Just add one line after the for loop:
oEntry.Items = ItemSet;
Let me know if this helps.

How to recursively keep on adding child object to parent if a child object is found on child

I have a scenario where I get list of child objects in json whose keys are like
{
"text": "Hellojson",
"child": [{
"somefirstchildkey": "somefirstchildValue",
"child": [{
"someSecondchildkey": "someSecondchildValue",
"child": [{
"someSecondchildkey": "someSecondchildValue",
"child": [{
}]
}]
}
]
}]
}
So this is like nested dynamic child . So right now, I am able to fetch parent and child but in this case there are continuous child getting added to child so in this case previous child will become parent of next child.
Code which I have implemented us:
for currentCategory in categories{
var parentCategory : rootParent?
// If the object exists use it
if let thisCategory = self.coreData.fetchWithPredicate(CoreDataEntities.MyCategories.rawValue, predicate: NSPredicate(format: "id = %# ,thisCategoryID)) as? [MyCategories],
firstObject = thisCategory.first {
parentCategory = firstObject
)
}
/// Insert a parent category as they're all top level from the API call
else {
parentCategory = self.coreData.insertNewObject(CoreDataEntities. MyCategories.rawValue,
keyValues: ["id" : currentCategory.id!]) as? MyCategories
Log.verbose?.message("Category inserted : \(parentCategory)")
}
/// Guard against if there are child categories
guard let children = currentCategory.children where children.count > 0 else {
// Save the context
self.coreData.saveStore()
continue
}
for thisChildCategory in children {
// If the child doesn't exist, then create a new one
// Guard ID
guard let thisChildID = thisChildCategory.id else {
Log.verbose?.message("Category Child insertion error : No Child ID")
continue
}
// Guard exisitance
if let currentChild = self.coreData.fetchWithPredicate(CoreDataEntities. MyCategories.rawValue, predicate: NSPredicate(format: "id == %#", thisChildID)) as? [MyCategories] where currentChild.count > 0 {
Log.verbose?.message("Category Child insertion not needed, already exists \(thisChildID), child \(currentChild)")
continue
}
// Create new object
if let currentChildCategory = self.coreData.insertNewObject(CoreDataEntities. MyCategories.rawValue,keyValues: ["id" : thisChildCategory.id!]) as? MyCategories {
// Set as parent category
currentChildCategory.parentCategory = parentCategory
// Save the context
self.coreData.saveStore()
Log.verbose?.message("Child Category Inserted \(currentChildCategory.id) with colours \(currentChildCategory.colours?.allObjects) and sizes \(currentChildCategory.sizes?.allObjects)")
}
}
}
So, using this code I am only able to access first level parent and its corresponding child , inner child and parents are not accessible.
I might have made some typos and also may have got the types a bit wrong but in general this should work. The function below will get the root for a child.
func getRootCategoryForChildCategory(_ child:MyCategories) -> rootParent
{
var recursiveCategory:rootParent = currentChildCategory.parentCategory
while(true)
{
if (recursiveCategory.parentCategory != nil)
{
recursiveCategory = recursiveCategory.parentCategory
}
else
{
return recursiveCategory
}
}
}
Then do, after:
// Set as parent category
currentChildCategory.parentCategory = parentCategory
self.getRootCatergoryForChildCategory(currentChildCategory).children.append(currentChildCategory)

Regex TypeError: Cannot read property '1' of null

My datepicker regular expression is trying matches on a null aray. How do I fix it? Not sure what clazz should equal if the array is null. I'm thinking a simple if (matches[1]) { etc } but I'm not sure what to do if matches is null. Clazz is used elsewhere twice in the code. Do I just set clazz to null or zero?
var matches = exp.match(IS_REGEXP);
var clazz = scope.$eval(matches[1]);
Edit: Here's where they use clazz
if (data.lastActivated !== newActivated) {
if (data.lastActivated) {
$animate.removeClass(data.lastActivated.element, clazz);
}
if (newActivated) {
$animate.addClass(newActivated.element, clazz);
}
data.lastActivated = newActivated;
}
Here's IS_REGEXP
11111111 22222222
var IS_REGEXP = /^\s*([\s\S]+?)\s+for\s+([\s\S]+?)\s*$/;
Double Edit:
Here's the whole function
function addForExp(exp, scope) {
var matches = exp.match(IS_REGEXP);
var clazz = scope.$eval(matches[1]);
var compareWithExp = matches[2];
var data = expToData[exp];
if (!data) {
var watchFn = function(compareWithVal) {
var newActivated = null;
instances.some(function(instance) {
var thisVal = instance.scope.$eval(onExp);
if (thisVal === compareWithVal) {
newActivated = instance;
return true;
}
});
if (data.lastActivated !== newActivated) {
if (data.lastActivated) {
$animate.removeClass(data.lastActivated.element, clazz);
}
if (newActivated) {
$animate.addClass(newActivated.element, clazz);
}
data.lastActivated = newActivated;
}
};
expToData[exp] = data = {
lastActivated: null,
scope: scope,
watchFn: watchFn,
compareWithExp: compareWithExp,
watcher: scope.$watch(compareWithExp, watchFn)
};
}
data.watchFn(scope.$eval(compareWithExp));
}
Setting clazz to null or empty string shall do, if clazz is all your concern.
var clazz = matches ? scope.$eval(matches[1]) : '';
But with compareWithExp, it might be better to exit from the whole logic when there is no match:
if ( ! matches ) return;

grails object references an unsaved transient instance - save the transient instance before flushing

I know that this question has many questions around in Stackoverflow but even though it has many answers about it, thoses answers couldn't help me at all and either figured it out yet.
In my WebAPP it works normal, but when I transform it to an API it fails(topic title error)... I have tried following:
save first Test(flush:true) // error the C must be NOT NULL
save testInstance.addToAs(a).save() //b and c
Why I can't save the whole object?
Domain Water
static hasMany = [personWaters : Person,
equipmentWaters: Equipment,
sampleWaters : WaterSample]
Domain WaterSample
static belongsTo = [water: Water]
Controller refactored some parts
def save() {
def waterParams = request.JSON
def sampleList = [] as Set
def equipmentList = [] as Set
def personList = [] as Set
waterAPIService.personPopulate(waterParams.personWaters, personList)
waterAPIService.equipmentPopulate(waterParams.equipmentWaters, equipmentList)
waterAPIService.samplePopulate(waterParams.sampleWaters, sampleList)
Date validity = Date.parse("yyyy-MM-dd'T'HH:mm:ss'Z'", waterParams.validity)
Date sample = Date.parse("yyyy-MM-dd'T'HH:mm:ss'Z'", waterParams.sampleDate)
waterParams.remove('personWaters')
waterParams.remove('equipmentWaters')
waterParams.remove('sampleWaters')
waterParams.remove('validity')
waterParams.remove('sampleDate')
waterParams.put('personWaters', personList)
waterParams.put('equipmentWaters', equipmentList)
waterParams.put('sampleWaters', sampleList)
waterParams.put('validity', validity)
waterParams.put('sampleDate', sample)
def waterInstance = new Water(waterParams)
//def test = waterAPIService.sampleValidated(sampleList ? sampleList.size() : 0, sampleList)
def test = 99
if (test == 99) {
if (saveTest(waterInstance)) {
render([message: ['ok']] as JSON)
} else {
def errors = []
errors.add('Erro ao salvar')
errors = waterInstance.errors.allErrors.collect { g.message([error: it]) }
render([message: errors] as JSON)
}
} else {
render render([message: ["Critério de estabilização não atendido para o parâmetro " + waterAPIService.messageSampleValidated(test)]] as JSON)
}
}
def saveTest(Water waterInstance) {
try {
println waterInstance.validate()
if (!waterInstance.hasErrors() && waterInstance.save() && waterInstance.validate()) {
return true
} else {
log.info("error", waterInstance.errors)
return false
}
} catch (e) {
log.info("exception error", e)
}
}
Service
def personPopulate(personWaters, personList) {
personWaters.each {
personList << Person.get(it.id)
}
return personList
}
def equipmentPopulate(equipmentWaters, equipmentList) {
equipmentWaters.each {
equipmentList << Equipment.get(it.id)
}
return equipmentList
}
def samplePopulate(sampleWaters, sampleList) {
sampleWaters.each {
def sample = new WaterSample()
sample.dateTime = Date.parse("yyyy-MM-dd'T'HH:mm:ss", it.dateTime)
sample.levelWater = it.levelWater
sample.conductivity = it.conductivity
sample.dissolvedOxygen = it.dissolvedOxygen
sample.redoxPotential = it.redoxPotential
sample.ph = it.ph
sample.temperature = it.temperature
sampleList << sample
}
return sampleList
}
waterParam JSON
{
"climateCondition":"SUNNY",
"equipmentWaters":[
{
"id":2
},
{
"id":4
}
],
"personWaters":[
{
"id":86
},
{
"id":143
}
],
"sampleWaters":[
{
"ReportId":2,
"conductivity":0,
"IDWeb":0,
"dissolvedOxygen":0,
"dateTime":"2015-12-07T17:08:00Z",
"levelWater":0,
"ID":4,
"UpdateDate":"0001-01-01T00:00:00Z",
"ph":0,
"redoxPotential":0,
"temperature":0
},
{
"ReportId":2,
"conductivity":0,
"IDWeb":0,
"dissolvedOxygen":0,
"dateTime":"2015-12-07T17:09:00Z",
"levelWater":0,
"ID":5,
"UpdateDate":"0001-01-01T00:00:00Z",
"ph":0,
"redoxPotential":0,
"temperature":0
},
{
"ReportId":2,
"conductivity":0,
"IDWeb":0,
"dissolvedOxygen":0,
"dateTime":"2015-12-07T18:13:00Z",
"levelWater":0,
"ID":6,
"UpdateDate":"0001-01-01T00:00:00Z",
"ph":0,
"redoxPotential":0,
"temperature":0
}
]
}
Ok, this was a headache to find one of the solution:
If you trying to save an object, debug your it and inspect any of nested objects, for example: I'm sending approval.id: null, the object will give me below:
"approval":{
"class":"User",
"id":null
},
Which is trying to add a user with id null, whick wont find and wont save. So remove it from your json request.

Resources