2

I am having issue while parsing json. This issue is coming only if there is one set of record whether all columns are having value or with one or more columns empty value. Other cases it works fine.

My case classes for the input is below:

    case class Source(AccountNo: String, Name: String)
    case class HitsIndex(_index: String, _type: String, _id: String, _score: Double, _source: Source)
    case class HitsCount(total: Int, max_score: Double, hits: List[HitsIndex])
    case class Shards(total: Int, successful: Int, failed: Int, hits: HitsCount)
    case class ParseJson(took: Int, timed_out: Boolean, _shards: Shards)

Import statements:

import scala.collection.mutable._
import net.liftweb.json._
import net.liftweb.json.DefaultFormats
import net.liftweb.json.Serialization.write

Below is the code I tested:

 case class Uiresult(AccountNo: String, Name: String)

    val json = parse(jsonString)
    val elements = (json \\ "_source").children
    for (acct <- elements) {
      val m = acct.extract[Source]
      val res = write(Uiresult(m.accountNo,  (m.firstName.toString() + m.lastName.toString()))
      println(res)
    }

Desired output for one record:

Note: last name comes as an empty

[
{"AccountNo":"1234","Name":"Augustin "}
]

Note: All columns are having values

[
{"AccountNo":"1234","Name":"Augustin Wagstuff "}
]

But getting Error message like below:

 > Exception in thread "main" net.liftweb.json.MappingException: No usable value for AccountNo
    Did not find value which can be converted into java.lang.String
        at net.liftweb.json.Meta$.fail(Meta.scala:191)
        at net.liftweb.json.Extraction$.mkValue$1(Extraction.scala:357)
        at net.liftweb.json.Extraction$.net$liftweb$json$Extraction$$build$1(Extraction.scala:317)
        at net.liftweb.json.Extraction$$anonfun$14.apply(Extraction.scala:253)
        at net.liftweb.json.Extraction$$anonfun$14.apply(Extraction.scala:253)
        at scala.collection.immutable.List.map(List.scala:273)
        at net.liftweb.json.Extraction$.instantiate$1(Extraction.scala:253)
        at net.liftweb.json.Extraction$.newInstance$1(Extraction.scala:286)
        at net.liftweb.json.Extraction$.net$liftweb$json$Extraction$$build$1(Extraction.scala:315)
        at net.liftweb.json.Extraction$.net$liftweb$json$Extraction$$extract0(Extraction.scala:366)
        at net.liftweb.json.Extraction$.net$liftweb$json$Extraction$$extract0(Extraction.scala:199)
        at net.liftweb.json.Extraction$.extract(Extraction.scala:43)
        at net.liftweb.json.JsonAST$JValue.extract(JsonAST.scala:312)
        at com.aexp.prospect.atul.sample_01.JsonRead$$anonfun$1.apply(JsonRead.scala:115)
        at com.aexp.prospect.atul.sample_01.JsonRead$$anonfun$1.apply(JsonRead.scala:114)
        at scala.collection.immutable.List.map(List.scala:273)
        at com.aexp.prospect.atul.sample_01.JsonRead$.main(JsonRead.scala:114)
        at com.aexp.prospect.atul.sample_01.JsonRead.main(JsonRead.scala)
    Caused by: net.liftweb.json.MappingException: Did not find value which can be converted into java.lang.String
        at net.liftweb.json.Meta$.fail(Meta.scala:191)
        at net.liftweb.json.Extraction$.convert(Extraction.scala:403)
        at net.liftweb.json.Extraction$.net$liftweb$json$Extraction$$build$1(Extraction.scala:314)
        at net.liftweb.json.Extraction$.mkValue$1(Extraction.scala:351)
        ... 16 more

My Input Json: (lastName is empty)

Note: All columns are having values

{
  "took": 1,
  "timed_out": false,
  "_shards": {
    "total": 3,
    "successful": 3,
    "failed": 0
  },
  "hits": {
    "total": 1,
    "max_score": 2.2488084,
    "hits": [
      {
        "_index": "test_02",
        "_type": "test_type",
        "_id": "123456",
        "_score": 2.2488084,
        "_source": {
          "AccountNo": "06009625297",
          "firstName": "Augustin",
          "lastName": "Wagstuff "
        }
      }
    ]
  }
}   

Note: last name is empty

{
  "took": 1,
  "timed_out": false,
  "_shards": {
    "total": 3,
    "successful": 3,
    "failed": 0
  },
  "hits": {
    "total": 1,
    "max_score": 2.2488084,
    "hits": [
      {
        "_index": "test_02",
        "_type": "test_type",
        "_id": "123456",
        "_score": 2.2488084,
        "_source": {
          "AccountNo": "06009625297",
          "firstName": "Augustin",
          "lastName": ""
        }
      }
    ]
  }
}   

Json Object Print:

Example 1:
Here I noticed all the columns are having value. I selected only one set of record which is an issue.

json JObject(List(JField(took,JInt(1)),JField(timed_out,JBool(false)),JField(_shards,JObject(List(JField(total,JInt(3)),JField(successful,JInt(3)), JField(failed,JInt(0))))), JField(hits,JObject(List(JField(total,JInt(1)), JField(max_score,JDouble(2.2488084)), JField(hits,JArray(List(JObject(List(JField(_index,JString(test_02)), JField(_type,JString(test_type)), JField(_id,JString(123456)), JField(_score,JDouble(2.2488084)), JField(_source,JObject(List(JField(AccountNo,JString(06009625297)), JField(firstName,JString(Augustin)), JField(lastName,JString())))))))))))))))

Example : 2 Here I noticed that here the lastName is coming as empty. I selected only one set of record which is an issue. Can some one help me how to handle this case.

json JObject(List(JField(took,JInt(1)),JField(timed_out,JBool(false)),JField(_shards,JObject(List(JField(total,JInt(3)),JField(successful,JInt(3)), JField(failed,JInt(0))))), JField(hits,JObject(List(JField(total,JInt(1)), JField(max_score,JDouble(2.2488084)), JField(hits,JArray(List(JObject(List(JField(_index,JString(test_02)), JField(_type,JString(test_type)), JField(_id,JString(123456)), JField(_score,JDouble(2.2488084)), JField(_source,JObject(List(JField(AccountNo,JString(06009625297)), JField(firstName,JString(Augustin)), JField(lastName,JString())))))))))))))))

Example with 2 or more set of records in input:

Input is having 2 set of records (Extracted only 2 instead of 1): This does not produce any issue and produce the required output. If you notice that the first of record is same as the before example : 2 input but here it does not produce any error.

{
  "took": 1,
  "timed_out": false,
  "_shards": {
    "total": 3,
    "successful": 3,
    "failed": 0
  },
  "hits": {
    "total": 2,
    "max_score": 2.2488084,
    "hits": [
      {
        "_index": "test_02",
        "_type": "test_type",
        "_id": "123456",
        "_score": 2.2488084,
        "_source": {
          "AccountNo": "06009625297",
          "firstName": "Augustin",
          "lastName": "Wagstuff"
        },
               "hits": [
      {
        "_index": "test_02",
        "_type": "test_type",
        "_id": "789078",
        "_score": 2.2188084,
        "_source": {
          "AccountNo": "06009625297",
          "firstName": "Augustin",
          "lastName": "Jhonson"
        }
      }
    ]
  }
}

Output: It is coming as expected.

[
    {"AccountNo":"06009625297","Name":"Augustin Wagstuff "},
    {"AccountNo":"06009625297","Name":"Augustin Jhonson"},

    ]

acct value from the code:

When I try to display the contend in the acct (refer the variable in the code) when there is one set of records in the output, I see the first column only even though all the other columns in the input are having valid values.

acct JField(AccountNo,JString(1234))

When I try to display the contend in the acct (refer the variable in the code) when there is two set of records in the output, I see the first column only even though all the columns are having valid values.

acct JField(_source,JObject(List(JField(AccountNo,JString(06009625297)), JField(firstName,JString(Augustin)), JField(lastName,JString(Wagstuff)))))

acct JField(_source,JObject(List(JField(AccountNo,JString(06009625297)), JField(firstName,JString(Augustin)), JField(lastName,JString(Jhonson)))))

I suspect the issue when I iterate the list. Pls some one help me to fix.

Revathi P
  • 77
  • 13
  • I moved the information from the other question here instead. Check so I got all the relevant data, hope you can solve it – Shaido Mar 17 '18 at 01:29
  • Thank you Shaido. I see and the details are avialable in the link. Dave Whittaker ----> user:829752. Can one of you help me or link him for this question. https://stackoverflow.com/questions/25299474/using-lift-json-with-case-classes. Also see another answer but not able to get a solution: https://stackoverflow.com/questions/34170046/parse-json-using-liftweb-in-scala-with-no-usable-value – Revathi P Mar 18 '18 at 04:46
  • I updated more details about my issue. Especially what scenario I am getting this issue and capture the data before failure as well. Hope this will help to provide a solution. Let me know if you need more details. – Revathi P Mar 18 '18 at 06:34
  • can any one help me on this issue. – Revathi P Mar 23 '18 at 14:38

2 Answers2

0

I have created a code to handle when there is 1 or zero input records. 2 or more records were working (Thanks to Shaido). Below is the code, could some one suggest, whether this code can be constructed in a better way.

case class Source(AccountNo: fnameString, : String, lname: String)
case class HitsIndex(_index: String, _type: String, _id: String, _score: Double, _source: Source)
case class HitsCount(total: Int, max_score: Double, hits: List[HitsIndex])
case class Shards(total: Int, successful: Int, failed: Int)
case class ParseJson(took: Int, timed_out: Boolean, _shards: Shards, hits: HitsCount)

case class Uiresult(masterid: String, value: String)
case class ErrorMsg(searchType: String, error_message: String)

def formatResult(jsonString: String, searchType: String): String = {
  implicit val formats = DefaultFormats
  val json = JsonParser.parse(jsonString)

  val elements = (json \\ "_source").children
  if (elements.isEmpty == true) {
    implicit val formats = DefaultFormats
    return (List(write(ErrorMsg(searchType, "No Matching Record Found"))).mkString("[\n", ",\n", "\n]"))
  }
  if (json.extract[ParseJson].hits.total == 1) {
    val m = (json \\ "_source").extract[Source]
    val list = List(write(Uiresult(m.AccountNo.toString(), (m.fname.toString() + m.lname.toString() ))))
    return (list.mkString("[\n", ",\n", "\n]"))

  } else {
    val elements = (json \\ "_source").children
    val list = for (source <- elements) yield {
      println(" source " + source)
      val m = source.extract[Source]
      val list = List(write(Uiresult(m.AccountNo.toString(), (m.fname.toString() + m.lname.toString() ))))
    }
    return (list.mkString("[\n", ",\n", "\n]"))
  }
}
jwvh
  • 50,871
  • 7
  • 38
  • 64
Revathi P
  • 77
  • 13
0

There is a similar discussion happened at Parse json using liftweb in scala with no usable value

I also encountered this issue when I used lift-json_2.11 version as 3.2.0 After many trials finally I fixed this issue by using version 2.6.3

<dependency>
    <groupId>net.liftweb</groupId>
    <artifactId>lift-json_2.11</artifactId>
    <version>2.6.3</version>
</dependency>