swift - Recursive function to replace json objects -


i have json file:

[ { "person": {   "@id": "value1",   "name": "mattia" }, "person1": {   "@ref": "value1" }, "subpersons": [   {     "@id": "value2",     "name": "luca",     "key": {       "@ref": "value1"     }   },   {     "@ref": "value1"   },   {     "@id": "value3",     "subsubpersons": [       {         "again": {           "@ref": "value2"         }       }     ]   } ], "key": {   "subkey": {     "@ref": "value1"   } } } ] 

i need map objects contains @id replace @ref values related @id values mapped. i'd obtain this:

[ { "person": {   "@id": "value1",   "name": "mattia" }, "person1": {   "@id": "value1",   "name": "mattia" }, "subpersons": [   {     "@id": "value2",     "name": "luca",     "key": {       "@id": "value1",       "name": "mattia"     }   },   {     "@id": "value1",     "name": "mattia"   },   {     "@id": "value3",     "subsubpersons": [       {         "again": {           "@id": "value2",           "name": "luca",           "key": {             "@id": "value1",             "name": "mattia"     }         }       }     ]   } ], "key": {   "subkey": {     "@id": "value1",     "name": "mattia"   } } } ] 

i'm using class replace values:

import uikit import alamofire import alamofireobjectmapper import objectmapper import swiftyjson import swiftdate import async  class findandreplace {  var ids = dictionary<string, json>() var dictchanged = dictionary<string, json>() var isdictinit: bool = false  /*  * find , replace  */  func findandreplace (json: json) -> json {      findjsogids(json)     let replaced = replacejsogrefs(json, ids: ids)      return replaced }  /*  * find "@id" keys , map values related  */  func findjsogids (value: json) {      (key, subjson): (string, json) in value {          if (key == "@id") {             let mvalueforkey = value[key].stringvalue             ids[mvalueforkey] = value          }          if (subjson.type == type.dictionary || subjson.type == type.array) {             findjsogids(subjson)         }      } }  /*  * replace "@ref" keys fields mapped in ids  */  func replacejsogrefs (var value: json, var ids: dictionary<string, json>) -> json {      if (value.type == type.dictionary) {          var result = dictionary<string, json> ()         (key, subjson): (string, json) in value {             if (key == "@ref") {                 let mvalueforkey = value[key].stringvalue                  var isreplaced = false                  while (isreplaced == false) {                  (idkey, _): (string, json) in ids[mvalueforkey]! {                     if (idkey == "@ref") {                          print("found @ref in dictionary")                          let dictvaluereplaced = replacejsogrefs(ids[mvalueforkey]!, ids: ids)                         ids.updatevalue(dictvaluereplaced, forkey: mvalueforkey)                     }                 }                  }                  return ids[mvalueforkey]!               } else {                 result[key] = replacejsogrefs(subjson, ids: ids)             }         }         return json(result)      } else if (value.type == type.array) {          var result = [json]()          (_, subjson): (string, json) in value {             result.append(replacejsogrefs(subjson, ids: ids))         }          return json(result)      } else {         return value      }  }  } 

it works misses @ref values.

can please me?

thanks in advance.

edit

i'm using objectmapper map objects.

i think find-replace approach won't efficient since you'll have many passes on data (until can't find @ref strings).

you should leverage fact json models reference types semantics (as oppose value types) , parse such, keeping @ref in parsed objects faulted references. every object parse should add in cache can referenced @id. in second pass you'll go through cache rewiring each reference using cache built lookup table.

if every model implements following protocol

protocol refobject {     func updatereferences(using cache: [string: refobject]) } 

you can implement per-model have custom rewiring logic per each model class. here few examples of such model classes:

for wildcard represented {"@ref": "xxx"} in json i'd create pointer class point referred object.

class pointer: refobject {     let referredid: string     var referred: refobject!      init(referedid: string) {         self.referredid = referredid     }      func updatereferences(using cache: [string : refobject]) {         self.referred = cache[referredid]     } } 

for person can implement similar

class person: refobject {     let id: string     let name: string      var otherid: string?     var other: person?      init(id: string, name: string, otherid: string?) {         self.id = id         self.name = name         self.otherid = otherid     }      func updatereferences(using cache: [string : refobject]) {         other = otherid.flatmap{ cache[$0] as? person }     } } 

(this assumes person can have {"id": "xx", "name": "xx", "other": {"@ref": "xx"}} "other" other optional

this general approach , not particular implementation, domain specific depending on needs.

update there similar protocol called json api (misleading name imo, utilizes same approach of referencing json objects id). here implementation in swift: https://github.com/wvteijlingen/spine might worth checking out


Comments

Popular posts from this blog

java - Static nested class instance -

c# - Bluetooth LE CanUpdate Characteristic property -

JavaScript - Replace variable from string in all occurrences -