Cloud Function annotateImage() returns 'Unexpected token o in JSON at position 1' 到原生 iOS 应用程序

Cloud Function annotateImage() returns 'Unexpected token o in JSON at position 1' to native iOS app

我正在使用 Firebase Cloud Functions 为本机 iOS 移动应用创建 ImageAnnotator,遵循 iOS client and Cloud Function 的 Firebase 文档。然而,在调用 'annotateImage' 客户端时,错误 'Unexpected token o in JSON at position 1' 被 returned。我正在使用 XCode 13.

我的客户代码:

import Foundation
import Firebase
import Resolver

class ImageAnnotator: ObservableObject {
  @LazyInjected var functions: Functions
  @Published var annotatedText: String?
  @Published var error: NSError?

  func annotateImage(imageData: Data) {
    let base64encodedImage = imageData.base64EncodedString()

    let requestData = [
      "image": ["content": base64encodedImage],
      "features": ["type": "DOCUMENT_TEXT_DETECTION"],
      "imageContext": ["languageHints": ["en"]]
    ]

    functions.httpsCallable("annotateImage").call(requestData) { (result, error) in
      if let error = error as NSError? {
        self.error = error
        return
      }
      
      DispatchQueue.main.async {
        guard let annotation = (result?.data as? [String: Any])?["fullTextAnnotation"] as? [String: Any]
        else {
          return
        }
        print("%nComplete annotation:")
        let text = annotation["text"] as? String ?? ""
        print("%n\(text)")
        self.annotatedText = text
      }
    }
  }
}

我的index.js云函数代码:

const functions = require('firebase-functions');
const vision = require('@google-cloud/vision');
const client = new vision.ImageAnnotatorClient();
exports.annotateImage = functions.https.onCall(async (data, context) => {
  if (!context.auth) {
    throw new functions.https.HttpsError(
      "unauthenticated",
      "annotateImage must be called while authenticated."
    );
  }
  try {
    return await client.annotateImage(JSON.parse(data));
  } catch (e) {
    throw new functions.https.HttpsError("internal", e.message, e.details);
  }
});

什么可能导致此错误从 annotateImage() 调用 return?

我能够使用建议的解决方案解决错误 here:

  1. 将requestData的'features'字典值改为数组。
  2. 将 requestData 作为编码字符串 JSON 传递给 annotateImage()。

但还是行

guard let annotation = (result?.data as? [String: Any])?["fullTextAnnotation"] as? [String: Any]

return为零。

该行未正确解析结果对象。我通过将 result.data 串行向下转换为 NSArray,然后将 NSArray 的索引 0 索引为 NSDictionary 来解决 nil return。然后我能够以 [String: Any].

的形式访问 NSDictionary 的 fullAnnotatedText 字段

完整代码:

import Foundation
import Firebase
import Resolver

class ImageAnnotator: ObservableObject {
  @LazyInjected var functions: Functions
  @Published var annotatedText: String?
  
  func annotateImage(imageData: Data) {

    struct requestData: Encodable {
      let image: [String: Data]
      let features = [["type": "DOCUMENT_TEXT_DETECTION"]]

      init(imageData: Data) {
        image = ["content": imageData]
      }
    }

    let encoder = JSONEncoder()

    let encodedData = try! encoder.encode(requestData(imageData: imageData))
    let string = String(data: encodedData, encoding: .utf8)!

    functions.httpsCallable("annotateImage").call(string) { (result, error) in
      if let error = error as NSError? {
        if error.domain == FunctionsErrorDomain {
          let code = FunctionsErrorCode(rawValue: error.code)
          let message = error.localizedDescription
          let details = error.userInfo[FunctionsErrorDetailsKey]
          print("ERROR \(String(describing: message)), CODE \(String(describing: code)), DETAILS \(String(describing: details))")
        }
        return
      }
      
      print("Success.")
      
      DispatchQueue.main.async {
        /* Parse result object */
        guard let nsarray = result?.data as? NSArray
        else {
          return
        }
        
        guard let nsdictionary = nsarray[0] as? NSDictionary
        else {
          return
        }

        guard let fullTextAnnotation = nsdictionary["fullTextAnnotation"] as? [String: Any]
        else {
          return
        }
        
        let text = fullTextAnnotation["text"] as? String ?? ""
        print("Recognized text: \(text)")
      }
    }
  }
}