How to map Array/Dictionary data into custom observed object

Dear All,

I try very hard to map Array/Dictionary data into a custom observed object and I need support.

The custom input object:

    struct ImageAnnotation: Codable {
        
        let labelAnnotations: [LabelAnnotations]
        
        struct LabelAnnotations: Codable {
            let description: String
            let score: Double
        }
    }

The which maps (the constant ist just a test):


            do {
                
                let annotateImageResponse = try! JSONSerialization.data(withJSONObject: result!.data, options: .prettyPrinted)
                let decoder = JSONDecoder()
                let callResult = try! decoder.decode([ImageAnnotation].self, from: annotateImageResponse)
//              print(callResult.description)
                
                self.imageProperties = callResult.map { analyzeImage -> ImageProperties in
                    let description = callResult.description
                    let score = 9.2222
                    return ImageProperties(id: .init(), description: description, score: String(score))
            }
        }
    }
}

The object which is getting mapped:

Printing description of callResult:
([ImageAnnotation]) callResult = 1 value {
[0] = {
labelAnnotations = 10 values {
[0] = (description = "Water", score = 0.97719752788543701)
[1] = (description = "Sky", score = 0.96194434165954589)
[2] = (description = "Plant", score = 0.91662931442260742)
[3] = (description = "Nature", score = 0.89995390176773071)
[4] = (description = "Natural landscape", score = 0.88719385862350464)
[5] = (description = "Highland", score = 0.86607605218887329)
[6] = (description = "Waterfall", score = 0.86192798614501953)
[7] = (description = "Body of water", score = 0.85812240839004517)
[8] = (description = "Vegetation", score = 0.84910452365875244)
[9] = (description = "Mountain", score = 0.8452027440071106)
}
}
}

The observable object:

import Foundation

struct ImageProperties: Identifiable {

let id: UUID

let description: String

let score: String

}

Could you help me out please?

Thanks a lot

I don't quite understand the question.
example of ObservableObject:

class Model: ObservableObject {
    @Published var state: MyState = ...
    ... more if needed
}

where

struct MyState {
    var items: [Annotations] = ...
    ... more if needed
}

Your usage of json decoding looks strange... typically it is:

decoder.decode([ImageAnnotation].self, from: result.data)

i.e. without JSONSerialization step.

Dear tera,

Actually my question is how i can map this Array/Dictionary in callResult into the observable object below:

([ImageAnnotation]) callResult = 1 value {
[0] = {
labelAnnotations = 10 values {
[0] = (description = "Water", score = 0.97719752788543701)
[1] = (description = "Sky", score = 0.96194434165954589)
[2] = (description = "Plant", score = 0.91662931442260742)
[3] = (description = "Nature", score = 0.89995390176773071)
[4] = (description = "Natural landscape", score = 0.88719385862350464)
[5] = (description = "Highland", score = 0.86607605218887329)
[6] = (description = "Waterfall", score = 0.86192798614501953)
[7] = (description = "Body of water", score = 0.85812240839004517)
[8] = (description = "Vegetation", score = 0.84910452365875244)
[9] = (description = "Mountain", score = 0.8452027440071106)

import Foundation

struct ImageProperties: Identifiable {

let id: UUID

let description: String

let score: String

}

class ImageAnalyzer: ObservableObject {

@Published var imageProperties = ImageProperties

In other words, you have an array of

    struct LabelAnnotations: Codable {
        let description: String
        let score: Double
    }

and you want it to map to array of

struct ImageProperties: Identifiable {
    let id: UUID
    let description: String
    let score: String
}

Do you really need UUID? Maybe LabelAnnotations have unique description field? In which case you may use description as id:

    struct LabelAnnotations: Codable, Identifiable {
        var id: String { description }
        let description: String
        let score: Double
    }

Or, if description is not unique, and neither is the combination of description + score, maybe array index can act as an identifier for you?

    struct LabelAnnotations: Codable, Identifiable {
        let id: Int // 0, 1, 2, ...
        let description: String
        let score: Double
    }

Or maybe you don't need identifiable at all, just Hashable?

    struct LabelAnnotations: Codable, Hashable {
        let description: String
        let score: Double
    }

    // needs identifiable items
    // ForEach(items) { item in
    // }

    // ok with hashable items
    ForEach(items, id: \.self) { item in
    }

Or, perhaps there was some other identifier in your source material (where are you getting LabelAnnotations from?), and it's just a matter of propagating it? This is the best approach.