0

I have a class. I have overridden toString value. Now I want to map the value of toString output to the class. Is there any shortcut way ?

public class Cat {
    String name;
    int age;
    String color;

    public Cat(String name, int age, String color) {
        this.name = name;
        this.age = age;
        this.color = color;
    }

    @Override
    public String toString() {
        return "Cat{" + "name=" + name + ", age="+age+",color="+color+'}';
    }
}`

in short I want to map following value to the Cat class

String value = "Cat{name=Kitty,age=1,color=Black}"
Cat cat = // create a 'Cat'from 'value'

Thank you in advance.

Jorn Vernee
  • 31,735
  • 4
  • 76
  • 93
ramsharma
  • 3
  • 2
  • 2
    did you mean to create `Cat cat = new Cat("Kitty", 1, "Black");` then print the cat and you have what you want! – Youcef LAIDANI Apr 10 '18 at 10:18
  • You don't have to do anything extra, overriding the toString() does the trick for you. – N00b Pr0grammer Apr 10 '18 at 10:18
  • 3
    "Now I want to map the value of toString output to the class" This doesn't make any sense to me. Please can you rephrase? – Michael Apr 10 '18 at 10:18
  • 1
    What do you mean by **mapping**? – Roshana Pitigala Apr 10 '18 at 10:19
  • Are you trying to create a specific instance of Cat? Namely a one year old, black cat, named Kitty? Or would you like to always get the same result when calling toString(), regardless of the actual attribute values? (Wouldn't make much sense but hey) – Syn Apr 10 '18 at 10:20
  • It looks like you want to populate an instance of the Cat class with a String that contains the key/values. If it is the case, in Java it will require a lot of boiler plate code. – davidxxx Apr 10 '18 at 10:22
  • @davidxxx depending on what exactly it is he needs, he may indeed have to parse the string, but he could also just want to make a copy of the object in question, in which case some getters/constructors would be better suited than calling toString and then parsing it. – Syn Apr 10 '18 at 10:27
  • Let me rephrase again : I want to populate Cat class using previously generated value. Cat{name=Kitty,age=1,color=Black} – ramsharma Apr 10 '18 at 10:30
  • You want to instanciate a `Cat` where `toString` will output "_Cat{name=Kitty,age=1,color=Black}_" ?/! – AxelH Apr 10 '18 at 10:31
  • I've tried to clarify your question a bit, just [edit] it again if I've misunderstood it. – Jorn Vernee Apr 10 '18 at 10:42
  • @Syn I agree with you. It seems a XY issue where the OP searches the answer in a way that is not necessarily the correct one. – davidxxx Apr 10 '18 at 10:48

4 Answers4

0

You can do this using a regular expression:

Pattern catCapture = Pattern.compile(
        "Cat\\{name=(?<name>\\w*)\\s*,\\s*age=(?<age>\\d+)\\s*,\\s*color=(?<color>\\w*)\\}"
    );

String input = "Cat{name=Kitty,age=1,color=Black}";

Matcher matcher = catCapture.matcher(input);
Cat cat;
if(matcher.find()) {
    String name = matcher.group("name");
    int age = Integer.parseInt(matcher.group("age"));
    String color = matcher.group("color");
    cat = new Cat(name, age, color);
} else {
    throw new RuntimeException("Can not parse: " + input);
}

System.out.println(cat); // prints Cat{name=Kitty, age=1,color=Black}

The regular expression captures the 3 values name, age and color into groups (?<name>\\w*), (?<age>\\d+) and (?<color>\\w*) so you can then grab them. You still have to parse the age into an int though.

It also accounts for varying numbers of white space in between a comma and a value use \\s* (i.e. 0 or more white spaces).

See also these:

Jorn Vernee
  • 31,735
  • 4
  • 76
  • 93
  • Thank you very much Jorn. It will work for me. I was looking for some inbuilt system if there were any where I could be more lazy :D. – ramsharma Apr 10 '18 at 10:55
0

Finally my desired class looks like this one. Special thanks to @Jorn vernee

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Cat {
    String name;
    int age;
    String color;

    public Cat(String name, int age, String color) {
        this.name = name;
        this.age = age;
        this.color = color;
    }

    public Cat(String strValue){

        Pattern catCapture = Pattern.compile(
            "Cat\\{name=(?<name>\\w*)\\s*,\\s*age=(?<age>\\d+)\\s*,\\s*color=(?<color>\\w*)\\}"
        );

        Matcher matcher = catCapture.matcher(strValue);

        if(matcher.find()) {
            this.name = matcher.group("name");
            this.age = Integer.parseInt(matcher.group("age"));
            this.color = matcher.group("color");
        } else {
            throw new RuntimeException("Can not parse: " + strValue);
        }
    }

    @Override
    public String toString() {
        return "Cat{" + "name=" + name + ", age=" + age + ", color=" + color + '}';
    }
}
ramsharma
  • 3
  • 2
0

Consider GSON for your requirement.

From the user guide

class BagOfPrimitives {
  private int value1 = 1;
  private String value2 = "abc";
  private transient int value3 = 3;
  BagOfPrimitives() {
    // no-args constructor
  }
}

// Serialization
BagOfPrimitives obj = new BagOfPrimitives();
Gson gson = new Gson();
String json = gson.toJson(obj);  

And, deserialization, which is your use case:

// Deserialization
BagOfPrimitives obj2 = gson.fromJson(json, BagOfPrimitives.class);
sujit
  • 2,258
  • 1
  • 15
  • 24
0

This was what I was looking for ... Thank you sujit.

    Cat cat = new Cat("Kitty",1,"Black");
    Gson gson = new Gson();
    String json = gson.toJson(cat);  
    System.out.println(json);

    Cat cat2 = gson.fromJson(json, Cat.class);
    System.out.println(cat2.toString());
ramsharma
  • 3
  • 2