2015-09-07 17 views
8

Tôi có đoạn mã sau sử dụng bình xịt để deserialise một số JSON vào một lớp chữ thường, thông qua phương thức parseJson.Scala sử dụng các loại rõ ràng khi giải quyết các vấn đề liên quan như thế nào?

Tùy thuộc vào nơi JsonFormat ngầm định [MyCaseClass] được xác định (nội dòng hoặc được nhập từ đối tượng đồng hành) và liệu có loại rõ ràng được cung cấp khi được xác định hay không, mã có thể không biên dịch.

Tôi không hiểu tại sao việc nhập ẩn từ đối tượng đồng hành yêu cầu nó phải có loại rõ ràng khi được xác định, nhưng nếu tôi đặt nội tuyến thì đây không phải là trường hợp?

Điều thú vị là IntelliJ định vị chính xác các thông số tiềm ẩn (thông qua cmd-shift-p) trong mọi trường hợp.

Tôi đang sử dụng Scala 2.11.7.

bị hỏng Mã - nhập ký tự đại diện từ đối tượng đồng, suy ra loại:

import SampleApp._ 
import spray.json._ 

class SampleApp { 
    import MyJsonProtocol._ 
    val inputJson = """{"children":["a", "b", "c"]}""" 
    println(s"Deserialise: ${inputJson.parseJson.convertTo[MyCaseClass]}") 
} 

object SampleApp { 
    case class MyCaseClass(children: List[String]) 

    object MyJsonProtocol extends DefaultJsonProtocol { 
    implicit val myCaseClassSchemaFormat = jsonFormat1(MyCaseClass) 
    } 
} 

Kết quả trong:

Cannot find JsonReader or JsonFormat type class for SampleAppObject.MyCaseClass 

Lưu ý rằng điều tương tự sẽ xảy ra với một khẩu rõ ràng của myCaseClassSchemaFormat ngầm.

Mã Working # 1 - nhập ký tự đại diện từ đối tượng đồng, loại rõ ràng:

Thêm một loại rõ ràng để các JsonFormat trong đối tượng đồng hành gây ra mã để biên dịch:

import SampleApp._ 
import spray.json._ 

class SampleApp { 
    import MyJsonProtocol._ 
    val inputJson = """{"children":["a", "b", "c"]}""" 
    println(s"Deserialise: ${inputJson.parseJson.convertTo[MyCaseClass]}") 
} 

object SampleApp { 
    case class MyCaseClass(children: List[String]) 

    object MyJsonProtocol extends DefaultJsonProtocol { 
    //Explicit type added here now 
    implicit val myCaseClassSchemaFormat: JsonFormat[MyCaseClass] = jsonFormat1(MyCaseClass) 
    } 
} 

Working Mã số 2 - Ngụ ý nội dòng, loại được phỏng đoán:

Tuy nhiên, đặt các tham số ngầm trong dòng nơi chúng được sử dụng, mà không cần loại rõ ràng, cũng hoạt động!

import SampleApp._ 
import spray.json._ 

class SampleApp { 
    import DefaultJsonProtocol._ 

    //Now in-line custom JsonFormat rather than imported 
    implicit val myCaseClassSchemaFormat = jsonFormat1(MyCaseClass) 

    val inputJson = """{"children":["a", "b", "c"]}""" 
    println(s"Deserialise: ${inputJson.parseJson.convertTo[MyCaseClass]}") 
} 

object SampleApp { 
    case class MyCaseClass(children: List[String]) 
} 
+0

Đây là một trong những câu hỏi "đau khi tôi làm điều này", câu trả lời hay nhất gần như chắc chắn "không làm điều đó". Theo kinh nghiệm của tôi, các giá trị tiềm ẩn thiếu chú thích kiểu là một trong những nguồn gây nhầm lẫn phổ biến nhất, sự khác biệt giữa các phiên bản lạ trong hành vi, vv, trong Scala. –

+0

Hi Travis - thực sự, đây là một lỗi thú vị để làm việc xung quanh, nhưng tôi đoán chú thích loại thời gian tiếp theo sẽ là cổng gọi đầu tiên của tôi cho các vấn đề tương tự! Không chắc chắn nếu điều này được coi là một lỗi Scala hay không, nhưng có thể đặt một cái gì đó vào danh sách gửi thư/xem xét nâng cao một vấn đề chỉ trong trường hợp. – MrProper

+1

Trình biên dịch đưa ra một thông báo lỗi nói rằng 'phương pháp ngầm không có gì áp dụng ở đây vì nó xuất hiện sau điểm ứng dụng và nó thiếu một kiểu kết quả rõ ràng' vì vậy ít nhất là lỗi nhỏ để chẩn đoán và sửa lỗi :) – Hugh

Trả lời

3

Sau khi tìm kiếm được thông báo lỗi Huw nêu trong bình luận của mình, tôi đã có thể tìm thấy câu hỏi StackOverflow này từ năm 2010: Why does this explicit call of a Scala method allow it to be implicitly resolved?

Điều này dẫn tôi đến vấn đề này Scala tạo ra trong năm 2008, và đóng cửa trong năm 2011 : https://issues.scala-lang.org/browse/SI-801 ('? yêu cầu loại kết quả rõ ràng cho các chuyển đổi ngầm')

Martin tuyên bố:

tôi đã thực hiện một hơi hơn mỗi quy tắc nhái: Một chuyển đổi tiềm ẩn không có loại kết quả rõ ràng chỉ hiển thị trong văn bản theo định nghĩa riêng của nó. Bằng cách đó, chúng tôi tránh các lỗi tham chiếu tuần hoàn. Tôi đóng cửa ngay bây giờ, để xem cách hoạt động của nó. Nếu chúng ta vẫn có vấn đề, chúng ta sẽ quay trở lại vấn đề này.

này nắm giữ - nếu tôi xếp lại thứ tự các mã phá vỡ để các đối tượng đồng bị tuyên bố đầu tiên, sau đó mã biên dịch. (Vẫn còn hơi lạ!)

(Tôi nghi ngờ tôi không thấy phương pháp ngầm 'không áp dụng ở đây' tin nhắn vì tôi có giá trị tiềm ẩn thay vì chuyển đổi - mặc dù tôi giả định ở đây là nguyên nhân gốc giống nhau ở trên).

Các vấn đề liên quan