Unable to convert xml to object - Swift4 - swift

I have the following XML string. I am trying to parse with XMLMapper (3rd party library).
I need to create array of
The xml is as follow;
<RandomDecimals>
<decimal>98258979</decimal>
<decimal>1000002218</decimal>
<decimal>1000002102</decimal>
<decimal>1000005713</decimal>
<decimal>1000002035</decimal>
<decimal>1000001434</decimal>
<decimal>1000001066</decimal>
<decimal>1000001498</decimal>
<decimal>1000002313</decimal>
<decimal>1000016914</decimal>
<decimal>1000017021</decimal>
<decimal>1000019039</decimal>
<decimal>52373625</decimal>
</RandomDecimals>
The code to parse to object is as follows;
class DecimalElement: XMLMappable {
var nodeName: String!
var decimal: String?
required init(map: XMLMap) {
}
func mapping(map: XMLMap) {
decimal <- map["decimal"]
}
}
class Response: XMLMappable {
var nodeName: String!
var shouldReset: Bool!
var randomDecimals: [DecimalElement]?
required init(map: XMLMap) {
}
func mapping(map: XMLMap) {
randomDecimals <- map["RandomDecimals.decimal"]
shouldReset <- map["ShouldReset"]
}
As a summary, I need to take decimals into randomDecimals array. But the I need to do it with XMLMapper.
What am I doing wrong?
BR,
Erdem

If your XML looks something like this:
<root>
<ShouldReset>true</ShouldReset>
<RandomDecimals>
<decimal>98258979</decimal>
<decimal>1000002218</decimal>
<decimal>1000002102</decimal>
<decimal>1000005713</decimal>
<decimal>1000002035</decimal>
<decimal>1000001434</decimal>
<decimal>1000001066</decimal>
<decimal>1000001498</decimal>
<decimal>1000002313</decimal>
<decimal>1000016914</decimal>
<decimal>1000017021</decimal>
<decimal>1000019039</decimal>
<decimal>52373625</decimal>
</RandomDecimals>
</root>
then, you can solve your issue by replacing:
var randomDecimals: [DecimalElement]?
with:
var randomDecimals: [String]?
in your Response class.
class Response: XMLMappable {
var nodeName: String!
var shouldReset: Bool!
var randomDecimals: [String]?
required init(map: XMLMap) {
}
func mapping(map: XMLMap) {
randomDecimals <- map["RandomDecimals.decimal"]
shouldReset <- map["ShouldReset"]
}
}
You can also use Array of Int64 to map directly the decimal numbers:
var randomDecimals: [Int64]?
Hope this helps.

Related

XMLMapper: how do I serialize CDATA wrapped values?

CDATA deserialization works great out of the box. But how should I configure this mapping:
class MyData: XMLMappable {
var nodeName: String!
var cdataValue: String?
...
func mapping(map: XMLMap) {
cdataValue <- map.attributes["cdataValue"]
}
}
and when I call toXMLString():
let myData = MyData()
myData.cdataValue = "actualValue"
print(myData.toXMLString())
to eventually obtain something like this:
<cdataValue><![CDATA[ actualValue ]]></cdataValue>

ObjectMapper how can I change datatype while Mapping in Swift

I am using this ObjectMapper library to map JSON to Core Data object and Vice versa.
But the problem here is I cant type cast objects.
here
import ObjectMapper
class network: NSManagedObject, Mappable {
#NSManaged var localId: NSNumber?
#NSManaged var version: String?
#NSManaged var port: String?
required public init?(map: Map) {
let ctx = DbHelper .getContext()
let entity = NSEntityDescription.entity(forEntityName: "network", in: ctx)
super.init(entity: entity!, insertInto: ctx)
mapping(map: map)
}
public func mapping(map: Map) {
localId <- map["localId"]
port <- map["port"] // Returns Int but I want to save it as String
version <- map["version"] // Returns Int but I want to save it as String
}
}
Here how to save version and port as String when I get value from JSON as Int.
Hope I am clear in explaining my question, if further clarification required please let me know.
Thank You
In a lot of situations you can use the built-in transform class TransformOf to quickly perform a desired transformation. TransformOf is initialized with two types and two closures. The types define what the transform is converting to and from and the closures perform the actual transformation.
For example, if you want to transform a JSON String value to an Int you could use TransformOf as follows:
let transform = TransformOf<Int, String>(fromJSON: { (value: String?) -> Int? in
// transform value from String? to Int?
return Int(value!)
}, toJSON: { (value: Int?) -> String? in
// transform value from Int? to String?
if let value = value {
return String(value)
}
return nil
})
id <- (map["port"], transform)
Here is a more condensed version of the above:
id <- (map["port"], TransformOf<Int, String>(fromJSON: { Int($0!) }, toJSON: { $0.map { String($0) } }))
I hope you can find solution from this.
Solution get from: https://github.com/Hearst-DD/ObjectMapper

Using Object Mapping with Kinvey

I have an array of objects I'm trying to get out of one of my collections. I've followed along using their docs and also some Googling and I believe I'm close to the solution, however not close enough. Here's what I have:
class Clothing: Entity {
var categories: [Category]!
var gender: String!
override class func collectionName() -> String {
//return the name of the backend collection corresponding to this entity
return "categories"
}
override func propertyMapping(_ map: Map) {
super.propertyMapping(map)
categories <- map["clothing"]
gender <- map["gender"]
}
}
class Category: NSObject, Mappable{
var title: String?
var image: String?
convenience required init?(map: Map) {
self.init()
}
func mapping(map: Map) {
title <- map["category"]
image <- map["image"]
}
}
I'm able to get the right gender, but the array of categories doesn't seem to get mapped to the Category object. Any thoughts?
your model actually have one issue, as you can see at https://devcenter.kinvey.com/ios/guides/datastore#Model you should use let categories = List<Category>() instead of var categories: [Category]!. Here's the model that and test and worked:
import Kinvey
class Clothing: Entity {
let categories = List<Category>()
var gender: String!
override class func collectionName() -> String {
//return the name of the backend collection corresponding to this entity
return "clothing"
}
override func propertyMapping(_ map: Map) {
super.propertyMapping(map)
categories <- ("categories", map["categories"])
gender <- ("gender", map["gender"])
}
}
class Category: Object, Mappable{
var title: String?
var image: String?
convenience required init?(map: Map) {
self.init()
}
func mapping(map: Map) {
title <- ("category", map["category"])
image <- ("image", map["image"])
}
}
and here's a sample code how to save a new Clothing object
let casualCategory = Category()
casualCategory.title = "Casual"
let shirtCategory = Category()
shirtCategory.title = "Shirt"
let clothing = Clothing()
clothing.gender = "male"
clothing.categories.append(shirtCategory)
clothing.categories.append(casualCategory)
dataStore.save(clothing) { (result: Result<Clothing, Swift.Error>) in
switch result {
case .success(let clothing):
print(clothing)
case .failure(let error):
print(error)
}
}

Using AlamofireObjectMapper Error

I'm using AlamofireObjectMapper to map object from JSON,But no response retrieved.Here is my code
let articleAPI = "https://news-at.zhihu.com/api/4/news/latest"
Alamofire.request(articleAPI).responseObject {(response: DataResponse<ArticleResponse>) in
let contents = response.result.value
print((contents?.stories?[0].title)!)
the ArticleResponse object looks like the following:
import ObjectMapper
class ArticleResponse: Mappable {
var date: String?
var stories: [ArticleDetailResponse]?
var top_stories: [TopStoriesResponse]?
required init?(map: Map) {
}
func mapping(map: Map) {
date <- map["date"]
stories <- map["stories"]
top_stories <- map["top_stories"]
}
}
class ArticleDetailResponse: Mappable {
var images: [String]?
var type: Int?
var id: Int?
var ga_prefix: String?
var title: String?
var multipic: Bool?
required init?(map: Map) {
}
func mapping(map: Map) {
images <- map["images"]
type <- map["type"]
id <- map["id"]
ga_prefix <- map["ga_prefix"]
title <- map["title"]
multipic <- map["multipic"]
}
}
class TopStoriesResponse: Mappable {
var image: String?
var type: Int?
var id: Int?
var ga_prefix: String?
var title: String?
required init?(map: Map) {
}
func mapping(map: Map) {
image <- map["image"]
type <- map["type"]
id <- map["id"]
ga_prefix <- map["ga_prefix"]
title <- map["title"]
}
}
I am doing this according the AlamofireObjectMapper usage document.In addition to that,Is there anything else have to implement?

alamofire object mapper .. why print my project name?

Screenshot Here
Note: This is my first swift file
override func viewDidLoad() {
super.viewDidLoad()
let encodingURL = url.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
Alamofire.request(encodingURL!).responseObject { (response: DataResponse<channel>) in
let MovieResponse = response.result.value
print("결과: \(MovieResponse?.channel?.result as AnyObject)")
print("타이틀: \(MovieResponse?.channel?.title as AnyObject)")
print("토탈카운트: \(MovieResponse?.channel?.totalCount as AnyObject)")
print("전체:\(MovieResponse?.channel as AnyObject)")
print("아이템: \(MovieResponse?.channel?.item as AnyObject)")
print("배우:\(MovieResponse?.channel?.item.first?.actor as AnyObject)")
}
}
Note: second swift file
import Foundation
import ObjectMapper
class channel : Mappable {
var channel : channelComponents?
required init?(map: Map){ }
func mapping(map: Map) {
self.channel <- map["channel"]
}
}
class channelComponents : Mappable {
var totalCount : Int?
var result : Int?
var title : String?
var item : [item]
required init?(map: Map){
item = []
}
func mapping(map: Map) {
self.totalCount <- map["totalCount"]
self.result <- map["result"]
self.title <- map["q"]
self.item <- map["item"]
}
}
class item : Mappable {
var actor : [Actor]
required init?(map: Map) {
actor = []
}
func mapping(map: Map) {
self.actor <- map["actor"]
}
}
class Actor : Mappable {
var content : String?
var link : String?
required init?(map: Map) { }
func mapping(map: Map) {
self.content <- map["content"]
self.link <- (map["link"])
}
}
input
print("아이템: \(MovieResponse?.channel?.item as AnyObject)")
print("배우:\(MovieResponse?.channel?.item.first?.actor as AnyObject)")
output
아이템: (
"Movie_D.item"
)
배우:(
"Movie_D.Actor",
"Movie_D.Actor",
"Movie_D.Actor",
"Movie_D.Actor",
"Movie_D.Actor",
"Movie_D.Actor",
"Movie_D.Actor"
)
Movie_D is my project name.
I want to know the actor's name, but there is just my project name. (the count is right)
You should cast the actor property to a String (assuming it is one) to properly display the actor's name in your print statement.
print("배우:\(String(describing: MovieResponse?.channel?.item.first?.actor))")