Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

328
Visualizações
Serializar [String:Any] a JSON

Estoy probando Swift en Linux.

Tengo datos en forma de diccionarios con claves de cadena y valores de cualquier tipo, y estoy tratando de serializarlos en una cadena en formato JSON.

NSJSONSerialization.dataWithJSONObject no funcionó, se queja Argument type '[String : Any]' does not conform to expected type 'AnyObject'

 let dict : [String : Any] = [ "string" : "Hello", "int" : 1, "double" : 3.14, "array str" : ["a", "b", "c"], "array double" : [1.0, 2.0, 3.0], "array int" : [1, 2, 3] ]

Sé que debe ser factible, ya que la representación de cadenas del diccionario ya está casi en el formato correcto:

 print("\(dict)") ["array int": [1, 2, 3], "int": 1, "array double": [1.0, 2.0, 3.0], "string": "Hello", "double": 3.1400000000000001, "array str": ["a", "b", "c"]]

Antes de sugerir declarar dict como [String:AnyObject] , el diccionario se llena con datos dinámicos, no se declara como un literal.

Si es posible, me gustaría limitar el uso de bibliotecas específicas de OSX o iOS que podrían no estar disponibles en el servidor.

Editar:

Aquí hay una implementación de la solución propuesta por Enrico Granata:

 protocol JSONSerializable { func toJSON() -> String? } extension String : JSONSerializable { func toJSON() -> String? { return "\"\(self)\"" } } extension Int : JSONSerializable { func toJSON() -> String? { return "\(self)" } } extension Double : JSONSerializable { func toJSON() -> String? { return "\(self)" } } extension Array : JSONSerializable { func toJSON() -> String? { var out : [String] = [] for element in self { if let json_element = element as? JSONSerializable, let string = json_element.toJSON() { out.append(string) } else { return nil } } return "[\(out.joinWithSeparator(", "))]" } } extension Dictionary : JSONSerializable { func toJSON() -> String? { var out : [String] = [] for (k, v) in self { if let json_element = v as? JSONSerializable, let string = json_element.toJSON() { out.append("\"\(k)\": \(string)") } else { return nil } } return "{\(out.joinWithSeparator(", "))}" } }
over 4 years ago · Santiago Trujillo
3 Respostas
Responde à pergunta

0

Estoy seguro de que habrá algunos errores en la forma en que lo expresaré, ya que es un tema complicado, pero tengan paciencia conmigo.

NSJSONSerialization es una API básica, no una biblioteca estándar de Swift. Como tal, proviene de Objective-C en Darwin, aunque probablemente se haya vuelto a implementar en Linux. La API original, nuevamente, es una API de Objective-C que en OS X se conecta a Swift.

El puente ocurre en términos de tipos de referencia (AnyObject). En Objective-C, eso es bastante bueno ya que todas las cosas que son objetos de Objective-C son tipos de referencia a los que se puede hacer referencia como un tipo común (id, o en Swift, AnyObject). Del lado de Swift puro, hay tipos que no son tipos de referencia (Array, Dictionary, Int, String, ...). Todo eso puede describirse, como parece que ya sabe, como confirmación de un protocolo mágico llamado Cualquiera. Any es realmente solo un alias de tipo para protocol<>, pero la magia del compilador existe a su alrededor.

Por compatibilidad con su versión original de Darwin, a NSJSONSerialization de Foundation le gusta hablar en términos de AnyObject, no en términos de Any. Como tal, existen tipos que no puede serializar.

Puedo ver algunas vías:

a) podría explotar el protocolo Bridgeable para intentar pasar de [String: Any] a [String: X where X: Bridgeable] (sintaxis no real)

Si observa https://github.com/apple/swift-corelibs-foundation/blob/master/Foundation/NSArray.swift , verá que Foundation agrega:

 extension Array : Bridgeable { public func bridge() -> NSArray { return _nsObject } }

Debería poder usar esto para atravesar su gráfico de objetos y obtener una versión NS* de sus objetos Swift puros, que luego estaría bien para pasar a NSJSONSerialization. Por supuesto, su kilometraje puede variar, ya que no todo es necesariamente puenteable sin pérdidas.

b) podría escribir su propio serializador JSON que pueda manejar los tipos de Swift nativos

Si sigues este camino, dejarás de preocuparte por Any o AnyObject o lo que sea. Sencillamente, harías algo como

 protocol JSONSerializable { func toJSON() -> String? }

y luego para una matriz,

 extension Array : JSONSerializable { func toJSON() -> String? { out = "[" for element in self { if let json_element = element as? JSONSerializable { if let string = json_element.toJSON() { out = out + string } else { return nil } } out = out + "]" return out } }

Cabe señalar que este código (a) no es una implementación completa tal cual, (b) tampoco es necesariamente la forma más inteligente y eficiente. Considéralo una pista en la dirección de lo que tendrías que hacer. Si sigue este camino, perderá parte de la reutilización del código y tendrá que preocuparse por las peculiaridades que tenga la sintaxis JSON, pero por otro lado, obtendrá un control bastante completo sobre el proceso de serialización y podrá dejar de preocuparse por Any.

over 4 years ago · Santiago Trujillo Relatório

0

Con Swift 3.0 Preview 3, solo puede hacer:

 JSONSerialization.data( withJSONObject: dict.bridge() )
over 4 years ago · Santiago Trujillo Relatório

0

Incluso si no le gusta escucharlo, [String: AnyObject] es el camino a seguir. Y no le veo ningún inconveniente. Cubre muy bien todos los tipos de datos que son serializables a JSON. Y se puede llenar fácilmente de forma dinámica.

Probado en XCode Playground:

 let dict : [String : AnyObject] = [ "string" : "Hello", "int" : 1, "double" : 3.14, "array str" : ["a", "b", "c"], "array double" : [1.0, 2.0, 3.0], "array int" : [1, 2, 3] ] let jsonData = try! NSJSONSerialization.dataWithJSONObject(dict, options: [.PrettyPrinted]) let x = String(data: jsonData, encoding: NSUTF8StringEncoding)! print(x)

Producción:

 { "array double" : [ 1, 2, 3 ], "array str" : [ "a", "b", "c" ], "int" : 1, "array int" : [ 1, 2, 3 ], "string" : "Hello", "double" : 3.14 }
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda