0

sorry for duplicating the question, but my problem is other. I have JSON parser method where I parse from json-string to map. But json-string has a value which is json-string too. Something like that:

    {
   "status_code":"255",
   "data":"{\"user\":{\"idpolzovatel\":1,\"id_poluch_tip\":1,\"fio_polzovatel\":\"Andrew Artificial\",\"login\":\"imi\",\"parol\":\"698d51a19d8a121ce581499d7b701668\",\"key\":null,\"nachalnik\":1,\"buhgalter\":0,\"delopr\":1},\"token\":\"230047517dd122c8f8116a6fa591a704\"}",
   "message":"Successfull!"
}

So, my parse-method:

public Map<String, String> convertToMapFromJSON(String res){
    ObjectMapper objectMapper = new ObjectMapper();
    Map<String, String> response = new HashMap<String, String>();
    try {
        response = objectMapper.readValue(res, new TypeReference<Map<String, String>>);
        int t = 0;
    } catch (IOException e) {
        e.printStackTrace();
    }
    return response;
}

I get response in client:

ResponseEntity<String> responseEntity = restTemplate.postForEntity(REST_SERVICE_URI + "/auth/", data, String.class);

get body

String res = responseEntity.getBody();//получаем тело запроса в формате JSON

then use those method:

Map<String, String> response = convertToMapFromJSON(res);

Map<String, String> data1 = convertToMapFromJSON(response.get("data"));

Map<String, String> userDetailes = convertToMapFromJSON(data1.get("user"));

but, when I use last method data1.get("user"); I get exception:

java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to java.lang.String

ok, got it. So, data1.get("user") isn't a string, it's linkedHashMap. So, I could do this then:

Map<String, String> userDetailes = data1.get("user");

? But then I get the error, where IDE say me, that data1.get("user") is a string.

Screenshot from debugger: enter image description here

So, how can I get this LinkedHashMap with my userdata? Sorry, for my english. Thank you.

Artificial
  • 23
  • 1
  • 6
  • Possible duplicate of [creating Hashmap from a JSON String](http://stackoverflow.com/questions/22011200/creating-hashmap-from-a-json-string) – DimaSan Nov 08 '16 at 12:51
  • sometimes SDE have problems; try to clean project and rebuild... and try to build from command line (maven or javac) so you are not dependent on the IDE compiler – OhadR Nov 08 '16 at 13:50
  • Updates your question with real JSON payload and used library (Jackson ?) – LoganMzz Nov 08 '16 at 15:25
  • update the question. yes, I've used Jackson library. – Artificial Nov 09 '16 at 08:06

2 Answers2

0

Looks like ObjectMapper has decoded the string to be of JSON format and has parsed it for you. You could just add a new method to parse (data1.get("user")) which returns a Map.

Curious
  • 453
  • 4
  • 15
0

Java apply type erasure for generics. It checks type correctness at compile time and then remove generic signature in compile code (ByteCode). Therefore, there's no check at runtime.

See this example which have same behaviour as your JSON library:

/** Returns a generic map which all keys are string but not values **/
T <T extends Map> raw(Class<T> clazz) {
    Map object = new LinkedHashMap();
    object.put("string", "This is a String");
    object.put("map"   , new LinkedHashMap());
    return (T) object;
}

Here is your code:

/** codes you try to execute/write **/
void withStringValues() {
    Map<String,String> object = raw(Map<String,String>.class);
    String string = object.get("string"); // Ok
    String map    = object.get("map");    // ClassCastException
    Map    map    = object.get("map");    // Doesn't compile
}

As you can see the call to raw is considered valid as compiled code don't check for generics. But it makes an invalid and implicit cast from Map to Map<String,String> which actually doesn't occured in compiled code.

Generics are remove and is the compiled version:

void withTypeErasure() {
    Map object = raw(Map.class);
    String string = (String) object.get("string");
    String map    = (String) object.get("map");
}

As you can see, Java compiler has removed all generic and adds necessary casts. You can see what's going wrong here.

Your real code must look like this:

void withRealValues() {
    Map<String,Object> object = raw(Map<String,Object>.class);
    String             string = (String) object.get("string"); // Ok
    Map<String,Object> map    = (Map) object.get("map");       // Ok
}
LoganMzz
  • 1,597
  • 3
  • 18
  • 31