I have this json:
{
"data":[
{
"id": "Character_Alien",
"name": "Trespasser",
"description": "Invader",
"type": {
"value": "outfit",
"displayValue": "Outfit",
"backendValue": "AthenaCharacter"
},
"rarity": {
"value": "uncommon",
"displayValue": "Uncommon"
},
"series": null,
"set": null,
"introduction": {
"chapter": "2022",
"text": "Introduced in 2022",
"backendValue": 22
},
"images": {
"smallIcon": "https://smallimage.png",
"icon": "https://image.png",
"featured": "https://imagebig.png",
"other": null
},
"variants": null,
"searchTags": null,
"metaTags": null
},
{
"id": "Character_Knowing",
"name": "Sinister",
"description": "He holds your fate.",
"type": {
"value": "outfit",
"displayValue": "Outfit",
"backendValue": "AthenaCharacter"
},
"rarity": {
"value": "rare",
"displayValue": "Rare",
"backendValue": "EFortRarity::Rare"
},
"series": null,
"set": {
"value": "Malice",
"text": "Path.",
"backendValue": "GripHate"
},
"introduction": {
"chapter": "2021",
"backendValue": 22
},
"images": {
"smallIcon": "https://smallimage.png",
"icon": "https://image.png",
"featured": "https://imagebig.png",
"other": null
},
"variants": null,
"searchTags": null,
"metaTags": null
}
]
}
It is a JSON 50000+ lines long this is just 2 of the objects of the JSON. I would like to get the "name", the "images" and the "rarity" values only if the "displayValue" is "Outfit". There are a lot of different displayValues so I want to filter the Outfit value first and then I can figure out how to filter the other ones.
I would like to do it in C# but if it can be done easier using Java I can do it there too(I have basic knowledge on both of them)
I have this in mind:
Foreach object in the json
If the object.displayValue = outfit then
string name = object.name
string imagesmall = object.imagesmall
string image = object.image
string imagebig = object.imagebig
String rariry = object.rarity
If it can be done this way, I then want to generate an image for each outfit with the name and rarity in it as text.
Any links to a similar question would be appreciated, It is the 3rd day that I am looking how to do this and this is my last resort.
.Net 6 (no external libraries needed):
using System;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Linq;
string json = "....."; // Removed for brevity
var results = ((JsonArray)(JsonNode.Parse(json))["data"])
.Where(o => (string)(o["type"]["displayValue"]) == "Outfit")
.Select(o => new
{
Name = (string)o["name"],
ImageSmall = (string)o["images"]["smallIcon"],
Image = (string)o["images"]["icon"],
ImageBig = (string)o["images"]["featured"],
Rarity = (string)o["rarity"]["value"]
});
foreach (var x in results) {
Console.WriteLine(x);
}
Output:
{ Name = Trespasser, ImageSmall = https://smallimage.png, Image = https://image.png, ImageBig = https://imagebig.png, Rarity = uncommon }
{ Name = Sinister, ImageSmall = https://smallimage.png, Image = https://image.png, ImageBig = https://imagebig.png, Rarity = rare }
You can be done this using Newtonsoft.Json NuGet easily. I have used the JSON as the string for the example. You can add your source for the relevant.
In case if you have a larger JSON with more attributes, you can use the Past Special option in Visual Studio to create the object Check Here
using Newtonsoft.Json;
public class Program
{
public static void Main()
{
string json = "{" +
"\n\"data\":[\n" +
"{\n\"id\":\"Character_Alien\",\n\"name\": \"Trespasser\",\n\"description\": " +
"\"Invader\",\n\"type\": {\n\"value\": \"outfit\",\n\"displayValue\": \"Outfit\",\n\"backendValue\": " +
"\"AthenaCharacter\"\n},\n\"rarity\": {\n\"value\": \"uncommon\",\n\"displayValue\": \"Uncommon\"\n}" +
",\n\"series\": null,\n\"set\": null,\n\"introduction\": {\n\"chapter\": \"2022\",\n\"text\": \"Introduced in 2022\"," +
"\n\"backendValue\": 22\n}," +
"\n\"images\": {\n\"smallIcon\": \"https://smallimage.png\",\n\"icon\": \"https://image.png\"," +
"\n\"featured\": \"https://imagebig.png\",\n\"other\": null\n},\n\"variants\": null,\n\"searchTags\": null," +
"\n\"metaTags\": null\n},\n{\n\"id\": \"Character_Knowing\",\n\"name\": \"Sinister\"," +
"\n\"description\": \"He holds your fate.\",\n\"type\": {\n\"value\": \"outfit\",\n\"displayValue\": \"Outfit\"," +
"\n\"backendValue\": \"AthenaCharacter\"\n}," +
"\n\"rarity\": {\n\"value\": \"rare\",\n\"displayValue\": \"Rare\",\n\"backendValue\": \"EFortRarity::Rare\"\n}," +
"\n\"series\": null,\n\"set\": {\n\"value\": \"Malice\",\n\"text\": \"Path.\",\n\"backendValue\": \"GripHate\"\n}," +
"\n\"introduction\": {\n\"chapter\": \"2021\",\n\"backendValue\": 22\n},\n\"images\": " +
"{\n\"smallIcon\": \"https://smallimage.png\",\n\"icon\": \"https://image.png\",\n\"featured\": \"https://imagebig.png\"," +
"\n\"other\": null\n},\n\"variants\": null,\n\"searchTags\": null,\n\"metaTags\": null\n}\n]\n" +
"}";
var jsonArr = JsonConvert.DeserializeObject<JsonArr>(json);
var val = jsonArr.Data.Where(w => w.Type.Value == "outfit").Select(s => new Data
{
Name = s.Name,
Rarity = s.Rarity
}).ToList();
Console.WriteLine(json);
Console.ReadKey();
}
}
public class JsonArr
{
[JsonProperty(PropertyName = "data")]
public List<Data> Data { get; set; }
}
public class Data
{
[JsonProperty(PropertyName = "id")]
public string Id { get; set; }
[JsonProperty(PropertyName = "name")]
public string Name { get; set; }
[JsonProperty(PropertyName = "description")]
public string Description { get; set; }
[JsonProperty(PropertyName = "type")]
public DataType Type { get; set; }
[JsonProperty(PropertyName = "rarity")]
public Rarity Rarity { get; set; }
}
public class DataType
{
[JsonProperty(PropertyName = "value")]
public string Value { get; set; }
[JsonProperty(PropertyName = "displayValue")]
public string DisplayValue { get; set; }
[JsonProperty(PropertyName = "backendValue")]
public string BackendValue { get; set; }
}
public class Rarity
{
[JsonProperty(PropertyName = "value")]
public string Value { get; set; }
[JsonProperty(PropertyName = "displayValue")]
public string DisplayValue { get; set; }
[JsonProperty(PropertyName = "backendValue")]
public string BackendValue { get; set; }
}
Related
Using Java 1.8 and Spring Boot 1.5.6.RELEASE.
Am able to obtain a list of items from by parsing /etc/passwd and /etc/group inside an ArrayList & ArrayList.
Need to create the following Rest Endpoint:
HTTP GET /users/<uid>/groups
Return all the groups for a given user.
User:
public class User {
String name;
String password;
Integer uid;
Integer gid;
String comment;
String home;
String shell;
public User(String line) {
String[] items = line.split(":");
if (items.length != 7) {
throw new IllegalArgumentException("Need 7 items from " + line + " and there's only: " + items.length);
}
this.name = items[0];
this.password = items[1];
this.uid = Integer.parseInt(items[2]);
this.gid = Integer.parseInt(items[3]);
this.comment = items[4];
this.home = items[5];
this.shell = items[6];
}
// Getters & Setters omitted for brevity.
}
Group:
public class Group {
private Integer gid;
private String name;
private List<String> members;
public Group(String line) {
String[] items = line.split(":");
this.name = items[0];
this.gid = Integer.parseInt(items[2]);
if (items.length > 3){
this.members = Arrays.asList(items[3]);
}
}
// Getters & Setters omitted for brevity.
}
FileParserUtils:
public class FileParserUtils {
public static List<Group> parseFileForGroups(String line) {
List<Group> groups = null;
try (Stream<String> stream = Files.lines(Paths.get(line))) {
groups = stream.filter(s -> s.charAt(0) != '#').map(Group::new)
.collect(Collectors.toCollection(LinkedList::new));
}
catch (Exception e) {
e.printStackTrace();
}
return groups;
}
}
Service:
#Service
public class UserServiceImpl implements UserService {
#Override
public User findByUid(String line, Integer uid) {
List<User> allUsers = FileParserUtils.parseFileForUsers(line);
for (User user : allUsers) {
if (user.getUid() == uid) {
return user;
}
}
return null;
}
#Override
public List<Group> findByGroupsByUid(String line, Integer uid) {
User specificUser = findByUid(line, uid);
Integer userGid = specificUser.getGid();
List<Group> allGroups = FileParserUtils.parseFileForGroups(line);
List<Group> userGroups = new ArrayList<>();
for (Group group : allGroups) {
if (userGid == group.getGid()) {
userGroups.add(group);
}
}
return userGroups;
}
}
This issue is that not all User uids are the same as the Group's gids (see the gids & uids for "name":"_cyrus"):
Obtain a list of Users (along with their uids & gids):
HTTP GET /myservice/users:
Yields JSON Payload Response:
[
{
"name":"_cyrus",
"password":"*",
"uid":77,
"gid":6,
"comment":"Cyrus Administrator",
"home":"/var/imap",
"shell":"/usr/bin/false"
},
{
"name":"_mailman",
"password":"*",
"uid":78,
"gid":78,
"comment":"Mailman List Server",
"home":"/var/empty",
"shell":"/usr/bin/false"
},
{
"name":"_appserver",
"password":"*",
"uid":79,
"gid":79,
"comment":"Application Server",
"home":"/var/empty",
"shell":"/usr/bin/false"
},
{
"name": "_jabber",
"password": "*",
"uid": 84,
"gid": 84,
"comment": "Jabber XMPP Server",
"home": "/var/empty",
"shell": "/usr/bin/false"
}
]
Groups only have gids (and not uids):
[
{
"gid": 6,
"name": "mail",
"members": [
"_teamsserver"
]
}
{
"gid": 78,
"name": "_mailman",
"members": null
},
{
"gid": 79,
"name": "_appserverusr",
"members": null
},
{
"gid": 30,
"name": "_keytabusers",
"members": [
"_calendar,_jabber,_postfix"
]
}
]
So, when if I try to find all the groups that Jabber belongs to:
http://localhost:8080/MyService/users/84/groups
Get the following JSON Response Payload:
[
{
"gid": 84,
"name": "_jabber",
"members": [
"84",
"Jabber XMPP Server",
"/var/empty",
"/usr/bin/false"
]
}
]
Why is 84 inside the members JSON array?
This is supposed to return all groups for the given user:
[
{
"gid": 29,
"name": "certusers",
"members": [
"root,_jabber,_postfix,_cyrus,_calendar,_dovecot"
]
},
{
"gid": 30,
"name": "_keytabusers",
"members": [
"_calendar,_jabber,_postfix"
]
}
]
Is there a way to map (e.g. link the two ArrayLists together or is there a different data structure that would help me do this) the User.uids with Group.gids?
This is all in-memory so please don't mention the use of ORM or JDBC.
I am looking to merge the list 1 and List 2 inorder to get the expected output as below.
Both the lists are Java classes and also want to add to a new Java class on the expected structure.
I have tried looping through List1 and List2 but in vain.
Also tried using lambda expression but could not get the expected output.
Will post the code that I tried.
Any help is highly appreciated.
List 1(juniorArea):
{
“One”: [
"G13DA"
],
“Two”: [
"G13AA",
"G13AD"
]
}
List 2:
[
{
"subgroupCode": "G13AA",
"productGroup": [
{
"productCode": "G1A",
"productDescription": “Two 1"
},
{
"productCode": "G9B",
"productDescription": “Two 2"
}
]
},
{
"subgroupCode": "G13AD",
"productGroup": [
{
"productCode": "G4A",
"productDescription": “Two 3”
},
{
"productCode": "G9C",
"productDescription": “Two 4”
}
]
},
{
"subgroupCode": "G13DA",
"productGroup": [
{
"productCode": "G5M",
"productDescription": “One 1"
},
{
"productCode": "G9M",
"productDescription": “One 2"
}
]
}
]
Expected Output:
{
"juniorArea": [
{
"juniorAreaDescription": “One”,
"mechandisingGroup": [
{
"productCode": "G5M",
"productDescription": “One 1"
},
{
"productCode": "G9M",
"productDescription": “One 2"
}
]
},
{
"juniorAreaDescription": “Two”,
"mechandisingGroup": [
{
"productCode": "G1A",
"productDescription": “Two 1"
},
{
"productCode": "G9B",
"productDescription": “Two 2"
},
{
"productCode": "G4A",
"productDescription": “Two 3”
},
{
"productCode": "G9C",
"productDescription": “Two 4”
}
]
}
]
}
You will need to make use of Google's gson library to parse your json Strings and also create Additional Classes to hold the data for the same. Save your json String in Files to read the content and convert them to appropriate Objects.
The JSON Strings you have mentioned have error since you are using (“) at many places. Replace them with (") at all locations. This change is very important because if you don't do it you might get Exceptions or undesirable outputs.
Store your Json strings as follows:
List1.txt
{
"One": [
"G13DA"
],
"Two": [
"G13AA",
"G13AD"
]
}
List2.txt
[
{
"subgroupCode": "G13AA",
"productGroup": [
{
"productCode": "G1A",
"productDescription": "Two 1"
},
{
"productCode": "G9B",
"productDescription": "Two 2"
}
]
},
{
"subgroupCode": "G13AD",
"productGroup": [
{
"productCode": "G4A",
"productDescription": "Two 3"
},
{
"productCode": "G9C",
"productDescription": "Two 4"
}
]
},
{
"subgroupCode": "G13DA",
"productGroup": [
{
"productCode": "G5M",
"productDescription": "One 1"
},
{
"productCode": "G9M",
"productDescription": "One 2"
}
]
}
]
You will need to change the file paths of these two while Running the Program
Add the following classes
JuniorArea.class
public class JuniorArea {
private String juniorAreaDescription;
private List<MerchandisingGroup> mechandisingGroup;
public String getJuniorAreaDescription() {
return juniorAreaDescription;
}
public void setJuniorAreaDescription(String juniorAreaDescription) {
this.juniorAreaDescription = juniorAreaDescription;
}
public List<MerchandisingGroup> getMechandisingGroup() {
return mechandisingGroup;
}
public void setMechandisingGroup(List<MerchandisingGroup> mechandisingGroup) {
this.mechandisingGroup = mechandisingGroup;
}
#Override
public String toString() {
return "JuniorArea [juniorAreaDescription=" + juniorAreaDescription + ", mechandisingGroup=" + mechandisingGroup
+ "]";
}
}
JuniorAreaCollection.class
public class JuniorAreaCollection {
private List<JuniorArea> juniorArea;
public List<JuniorArea> getJuniorArea() {
return juniorArea;
}
public void setJuniorArea(List<JuniorArea> juniorArea) {
this.juniorArea = juniorArea;
}
#Override
public String toString() {
return "JuniorAreaCollection [juniorArea=" + juniorArea + "]";
}
}
MerchandisingGroup.class
public class MerchandisingGroup {
private String productCode;
private String productDescription;
public String getProductCode() {
return productCode;
}
public void setProductCode(String productCode) {
this.productCode = productCode;
}
public String getProductDescription() {
return productDescription;
}
public void setProductDescription(String productDescription) {
this.productDescription = productDescription;
}
#Override
public String toString() {
return "MechandisingGroup [productCode=" + productCode + ", productDescription=" + productDescription + "]";
}
}
Product.class
public class Product {
private String subgroupCode;
private List<ProductGroup> productGroup;
public String getSubgroupCode() {
return subgroupCode;
}
public void setSubgroupCode(String subgroupCode) {
this.subgroupCode = subgroupCode;
}
public List<ProductGroup> getProductGroup() {
return productGroup;
}
public void setProductGroup(List<ProductGroup> productGroup) {
this.productGroup = productGroup;
}
#Override
public String toString() {
return "Product [subgroupCode=" + subgroupCode + ", productGroup=" + productGroup + "]";
}
}
ProductGroup.class
public class ProductGroup {
private String productCode;
private String productDescription;
public String getProductCode() {
return productCode;
}
public void setProductCode(String productCode) {
this.productCode = productCode;
}
public String getProductDescription() {
return productDescription;
}
public void setProductDescription(String productDescription) {
this.productDescription = productDescription;
}
#Override
public String toString() {
return "ProductGroup [productCode=" + productCode + ", productDescription=" + productDescription + "]";
}
}
Finally run the follwing Main Class code, to check the output
public class MainRunner {
// Use Path according to your file system
private static String List1Path = "/List1.txt";
// Use Path according to your file system
private static String List2Path = "/List2.txt";
public static void main(String...arg) throws UnsupportedEncodingException, IOException {
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String List1Content = new String(Files.readAllBytes(Paths.get(List1Path)), "UTF-8");
Map<String, List<String>> map = new HashMap<>();
map = gson.fromJson(List1Content, new TypeToken<Map<String, List<String>>>() {}.getType());
System.out.println(map);
String List2Content = new String(Files.readAllBytes(Paths.get(List2Path)), "UTF-8");
List<Product> products = gson.fromJson(List2Content, new TypeToken<List<Product>>() {}.getType());
System.out.println(products);
List<JuniorArea> juniorAreas = new ArrayList<>();
for (String s : map.keySet()) {
JuniorArea juniorArea = new JuniorArea();
juniorArea.setJuniorAreaDescription(s);
List<MerchandisingGroup> merchandisingGroups = new ArrayList<>();
List<String> subgroupCodes = map.get(s);
for (String subgroupCode : subgroupCodes) {
for (Product product : products) {
if (product.getSubgroupCode().equals(subgroupCode)) {
List<ProductGroup> productGroups = product.getProductGroup();
for (ProductGroup productGroup : productGroups) {
MerchandisingGroup merchandisingGroup = new MerchandisingGroup();
merchandisingGroup.setProductCode(productGroup.getProductCode());
merchandisingGroup.setProductDescription(productGroup.getProductDescription());
merchandisingGroups.add(merchandisingGroup);
}
}
}
}
juniorArea.setMechandisingGroup(merchandisingGroups);
juniorAreas.add(juniorArea);
}
JuniorAreaCollection collection = new JuniorAreaCollection();
collection.setJuniorArea(juniorAreas);
System.out.println(gson.toJson(collection));
}
}
Output should be printed on your console
{
"juniorArea": [
{
"juniorAreaDescription": "One",
"mechandisingGroup": [
{
"productCode": "G5M",
"productDescription": "One 1"
},
{
"productCode": "G9M",
"productDescription": "One 2"
}
]
},
{
"juniorAreaDescription": "Two",
"mechandisingGroup": [
{
"productCode": "G1A",
"productDescription": "Two 1"
},
{
"productCode": "G9B",
"productDescription": "Two 2"
},
{
"productCode": "G4A",
"productDescription": "Two 3"
},
{
"productCode": "G9C",
"productDescription": "Two 4"
}
]
}
]
}
For example: Given this json document:
{
"store": {
"book": [
{
"category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
},
{
"category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
},
],
"bicycle": {
"color": "red",
"price": 19.95
}
},
"expensive": 10
}
I would like to produce (something like) this output:
store.book.category: "reference"
store.book.author: "Nigel Rees"
store.book.title: "Sayings of the Century"
store.book.price: 8.95
store.book.category: "fiction"
store.book.author: "Herman Melville"
store.book.title: "Moby Dick"
store.book.isbn: "0-553-21311-3"
store.book.price: 8.99
store.bicycle.color: "red"
store.bicycle.price: 19.95
expensive:10
Rather than work from raw text, I would prefer an efficient solution based on one of the robust json libraries (gson, jackson, etc.).
Here is a sample code with org.json. But the same can be used with Gson/Jackson with changes to appropriate types within those libraries. You could also using StringBuilder instead of String for the keys here.
import java.util.Iterator;
import org.json.JSONArray;
import org.json.JSONObject;
public class MyJSONTest {
private static void listJson(JSONObject json) {
listJSONObject("", json);
}
private static void listObject(String parent, Object data) {
if (data instanceof JSONObject) {
listJSONObject(parent, (JSONObject)data);
} else if (data instanceof JSONArray) {
listJSONArray(parent, (JSONArray) data);
} else {
listPrimitive(parent, data);
}
}
private static void listJSONObject(String parent, JSONObject json) {
Iterator it = json.keys();
while (it.hasNext()) {
String key = (String)it.next();
Object child = json.get(key);
String childKey = parent.isEmpty() ? key : parent + "." + key;
listObject(childKey, child);
}
}
private static void listJSONArray(String parent, JSONArray json) {
for (int i = 0; i < json.length(); i++) {
Object data = json.get(i);
listObject(parent + "[" + i + "]", data);
}
}
private static void listPrimitive(String parent, Object obj) {
System.out.println(parent + ":" + obj);
}
public static void main(String[] args) {
String data = "{\"store\":{\"book\":[{\"category\":\"reference\",\"author\":\"NigelRees\",\"title\":\"SayingsoftheCentury\",\"price\":8.95},{\"category\":\"fiction\",\"author\":\"HermanMelville\",\"title\":\"MobyDick\",\"isbn\":\"0-553-21311-3\",\"price\":8.99},],\"bicycle\":{\"color\":\"red\",\"price\":19.95}},\"expensive\":10}";
JSONObject json = new JSONObject(data);
System.out.println(json.toString(2));
listJson(json);
}
}
Turns out this is pretty easy to do using Gson, especially with the JsonReader.getPath() method introduced in 2.3.
static void parseJson(String json) throws IOException {
JsonReader reader = new JsonReader(new StringReader(json));
reader.setLenient(true);
while (true) {
JsonToken token = reader.peek();
switch (token) {
case BEGIN_ARRAY:
reader.beginArray();
break;
case END_ARRAY:
reader.endArray();
break;
case BEGIN_OBJECT:
reader.beginObject();
break;
case END_OBJECT:
reader.endObject();
break;
case NAME:
reader.nextName();
break;
case STRING:
String s = reader.nextString();
print(reader.getPath(), quote(s));
break;
case NUMBER:
String n = reader.nextString();
print(reader.getPath(), n);
break;
case BOOLEAN:
boolean b = reader.nextBoolean();
print(reader.getPath(), b);
break;
case NULL:
reader.nextNull();
break;
case END_DOCUMENT:
return;
}
}
}
static private void print(String path, Object value) {
path = path.substring(2);
path = PATTERN.matcher(path).replaceAll("");
System.out.println(path + ": " + value);
}
static private String quote(String s) {
return new StringBuilder()
.append('"')
.append(s)
.append('"')
.toString();
}
static final String REGEX = "\\[[0-9]+\\]";
static final Pattern PATTERN = Pattern.compile(REGEX);
I am getting an array size of zero for the "tweets" array when trying to access the arraylist that it should be stored in. I am using Jackon databinding to a class, which at this point has "worked" as in not gave any errors or exceptions. But, the problem is still that the array is returning empty.
Here is the method where I am accessing the class that the JSON is being binded to:
WeatherDatabaseCreator.java
//Read in files to be parsed.
for (int i = 0; i < twitterFiles.size(); i++) {
File twitterFile = twitterFiles.get(i);
WeatherTweetParser wtp = new WeatherTweetParser(twitterFile);
wtp.mapJavaObject();
tws = new Tweets();
tweets = tws.getTweets();
System.out.print(tweets.size());
tweetIndex = 0;
System.out.println("Parsing and inserting twitter file '" + twitterFile.getAbsolutePath() + "'...");
//Step through all the tweets in each file, using the TweetParser class.
while (true) {
tweet = tweets.get(tweetIndex);
user = tweet.new User();
entity = tweet.new Entities();
userMentions = entity.getUserMentions();
hashtags = entity.getHashtags();
if (tweet.getText() == null) {
break;
}
numParsed++;
Boolean success = wdbm.insertTweet(tweet, user);
if (success == true) {
numInserted++;
}
if (entity.getNumHashtags() > 0){
for (int j = 0; j < entity.getNumHashtags(); j++) {
wdbm.insertHashtag(tweet, hashtags.get(j));
}
}
if (entity.getNumUserMentions() > 0) {
for (int k = 0; k < entity.getNumUserMentions(); k++) {
wdbm.insertReference(tweet, userMentions.get(k));
}
}
if (numParsed % UPDATE_INTERVAL == 0) {
System.out.println(numParsed + " tweets parsed. " + numInserted + " tweets inserted into database...");
}
tweetIndex++;
}
Here is part of the JSON File. The file is made up of an array of tweets, with some nested classes. Here I included two elements of the array:
2014-01-03-11-03.terms.json
{
"tweets": [
{
"filter_level": "medium",
"contributors": null,
"text": "U know your ice fishing at home when ur snacks are sandwiches,chips,dips,beef jerky and all the goodies instead of just a case of beer #mom",
"geo": null,
"retweeted": false,
"in_reply_to_screen_name": null,
"truncated": false,
"lang": "en",
"entities": {
"symbols": [
],
"urls": [
],
"hashtags": [
{
"text": "mom",
"indices": [
135,
139
]
}
],
"user_mentions": [
]
},
"in_reply_to_status_id_str": null,
"id": 419137025376145408,
"source": "<a href=\"http://twitter.com/download/iphone\" rel=\"nofollow\">Twitter for iPhone<\/a>",
"in_reply_to_user_id_str": null,
"favorited": false,
"in_reply_to_status_id": null,
"retweet_count": 0,
"created_at": "Fri Jan 03 16:03:48 +0000 2014",
"in_reply_to_user_id": null,
"favorite_count": 0,
"id_str": "419137025376145408",
"place": null,
"user": {
"location": "",
"default_profile": false,
"profile_background_tile": true,
"statuses_count": 5411,
"lang": "en",
"profile_link_color": "17EBCF",
"profile_banner_url": "https://pbs.twimg.com/profile_banners/408240224/1384838946",
"id": 408240224,
"following": null,
"protected": false,
"favourites_count": 4222,
"profile_text_color": "333333",
"description": "It is what it is, no more, no less. Trust in the Lord. BSU Softball #5. My whole being is happy - Psalm 16:9",
"verified": false,
"contributors_enabled": false,
"profile_sidebar_border_color": "FFFFFF",
"name": "Nicole Anne",
"profile_background_color": "C0DEED",
"created_at": "Wed Nov 09 05:03:58 +0000 2011",
"default_profile_image": false,
"followers_count": 452,
"profile_image_url_https": "https://pbs.twimg.com/profile_images/413270299925164033/mWiJBKP2_normal.jpeg",
"geo_enabled": true,
"profile_background_image_url": "http://a0.twimg.com/profile_background_images/698793822/14d9ce538d96b435ad4449d5385a3ec1.jpeg",
"profile_background_image_url_https": "https://si0.twimg.com/profile_background_images/698793822/14d9ce538d96b435ad4449d5385a3ec1.jpeg",
"follow_request_sent": null,
"url": null,
"utc_offset": -32400,
"time_zone": "Alaska",
"notifications": null,
"profile_use_background_image": true,
"friends_count": 634,
"profile_sidebar_fill_color": "DDEEF6",
"screen_name": "NDupay",
"id_str": "408240224",
"profile_image_url": "http://pbs.twimg.com/profile_images/413270299925164033/mWiJBKP2_normal.jpeg",
"listed_count": 1,
"is_translator": false
},
"coordinates": null
},
{
"filter_level": "medium",
"contributors": null,
"text": "Just watched DeBlasio shovel snow for the cameras and I have to say, his form is terrible. Looks a bit inexperienced.",
"geo": null,
"retweeted": false,
"in_reply_to_screen_name": null,
"truncated": false,
"lang": "en",
"entities": {
"symbols": [
],
"urls": [
],
"hashtags": [
],
"user_mentions": [
]
},
"in_reply_to_status_id_str": null,
"id": 419137026458673152,
"source": "<a href=\"http://twitter.com/download/iphone\" rel=\"nofollow\">Twitter for iPhone<\/a>",
"in_reply_to_user_id_str": null,
"favorited": false,
"in_reply_to_status_id": null,
"retweet_count": 0,
"created_at": "Fri Jan 03 16:03:48 +0000 2014",
"in_reply_to_user_id": null,
"favorite_count": 0,
"id_str": "419137026458673152",
"place": null,
"user": {
"location": "",
"default_profile": false,
"profile_background_tile": false,
"statuses_count": 2609,
"lang": "en",
"profile_link_color": "FF8000",
"id": 163686045,
"following": null,
"protected": false,
"favourites_count": 204,
"profile_text_color": "333333",
"description": "Love learning, Hockey #NYR, music and photography. My family is my whole life.",
"verified": false,
"contributors_enabled": false,
"profile_sidebar_border_color": "EEEEEE",
"name": "Steven Marques",
"profile_background_color": "ACDED6",
"created_at": "Wed Jul 07 01:26:25 +0000 2010",
"default_profile_image": false,
"followers_count": 56,
"profile_image_url_https": "https://pbs.twimg.com/profile_images/378800000795958214/5e3ff928282ad692a36e941e5c5ff628_normal.jpeg",
"geo_enabled": false,
"profile_background_image_url": "http://abs.twimg.com/images/themes/theme18/bg.gif",
"profile_background_image_url_https": "https://abs.twimg.com/images/themes/theme18/bg.gif",
"follow_request_sent": null,
"url": null,
"utc_offset": -18000,
"time_zone": "Eastern Time (US & Canada)",
"notifications": null,
"profile_use_background_image": true,
"friends_count": 58,
"profile_sidebar_fill_color": "F6F6F6",
"screen_name": "SMGafanha",
"id_str": "163686045",
"profile_image_url": "http://pbs.twimg.com/profile_images/378800000795958214/5e3ff928282ad692a36e941e5c5ff628_normal.jpeg",
"listed_count": 2,
"is_translator": false
},
"coordinates": null
},
Here is the Java class that the JSON file is mapped to, followed by the class mapping the JSON to the class:
Tweets.java
public class Tweets {
private ArrayList<Tweet> tweets;
public Tweets() {
tweets = new ArrayList<Tweet>();
}
public ArrayList<Tweet> getTweets() {
return tweets;
}
public void setTweets(ArrayList<Tweet> tweets) {
this.tweets = tweets;
}
public static class Tweet {
private String text;
#JsonProperty("source")
private String postMethod;
#JsonProperty("created_at")
private String time;
#JsonProperty("id")
private String ID;
public Tweet() {
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getID() {
return ID;
}
public void setID(String iD) {
ID = iD;
}
public String getPostMethod() {
return postMethod;
}
public void setPostMethod(String postMethod) {
this.postMethod = postMethod;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public class User {
private String location;
#JsonProperty("screen_name")
private String user;
#JsonProperty("time_zone")
private String timeZone;
#JsonProperty("description")
private String accountDescription;
public User(){
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public String getTimeZone() {
return timeZone;
}
public void setTimeZone(String timeZone) {
this.timeZone = timeZone;
}
public String getAccountDescription() {
return accountDescription;
}
public void setAccountDescription(String accountDescription) {
this.accountDescription = accountDescription;
}
}
public class Entities {
#JsonProperty("user_mentions")
ArrayList<UserMention> userMentions;
#JsonProperty("hashtags")
ArrayList<Hashtag> hashtags;
public Entities() {
}
public ArrayList<UserMention> getUserMentions() {
return userMentions;
}
public int getNumUserMentions() {
return userMentions.size();
}
public UserMention getUserMention(int index) {
return userMentions.get(index);
}
public void setUserMentions(ArrayList<UserMention> userMentions) {
this.userMentions = userMentions;
}
public ArrayList<Hashtag> getHashtags() {
return hashtags;
}
public int getNumHashtags() {
return hashtags.size();
}
public Hashtag getHashtag(int index) {
return hashtags.get(index);
}
public void setHashtags(ArrayList<Hashtag> hashtags) {
this.hashtags = hashtags;
}
public class UserMention {
#JsonProperty("screen_name")
private String userRef;
public UserMention() {
}
public String getUserRef() {
return userRef;
}
public void setUserRef(String userRef) {
this.userRef = userRef;
}
}
public class Hashtag {
#JsonProperty("text")
private String hashText;
public Hashtag() {
}
public String getHashText() {
return hashText;
}
public void setHashText(String hashText) {
this.hashText = hashText;
}
}
}
}
}
WeatherTweetParser.java
public class WeatherTweetParser {
private static File twitterFile;
public WeatherTweetParser(File twitterFile) {
WeatherTweetParser.twitterFile = twitterFile;
}
public void mapJavaObject() {
String jsonFile = twitterFile.getName();
System.out.println("Mapping JSON to WeatherTweet Class.");
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
try {
mapper.readValue(new File(jsonFile), Tweets.class);
} catch (JsonParseException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Finished Mapping of JSON File.");
}
And here is the error:
Mapping JSON to WeatherTweet Class.
Finished Mapping of JSON File.
Tweets size: 0
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.rangeCheck(Unknown Source)
at java.util.ArrayList.get(Unknown Source)
at database.WeatherDatabaseCreator.main(WeatherDatabaseCreator.java:145)
Parsing and inserting twitter file 'C:\Users\Jared\Documents\Eclipse
WorkSpace\workspace\WeatherDatabaseCreator\2014-01-03-11-03.terms.json'...
On this line of WeatherDatabaseCreator.java:
tweet = tweets.get(tweetIndex);
TL:DR: I understand this error is because the index is out of range, because there is nothing obviously even in the tweets array. But, if the Jackson mapping of the JSON file to my Java Class went through without exceptions, why is the tweets array empty?
while (true) {
tweet = tweets.get(tweetIndex);
user = tweet.new User();
entity = tweet.new Entities();
userMentions = entity.getUserMentions();
hashtags = entity.getHashtags();
if (tweet.getText() == null) {
break;
}
The only break in this loop will work only if getText is null. If getText is not null for all the tweets, you'll get index out of bound exception.
Instead of while(true) you should probably use a check like tweetIndex < tweets.size()
The second problem. You create a Tweets object without loading any items there:
wtp.mapJavaObject();
tws = new Tweets();
tweets = tws.getTweets();
Of course tws object will not have any tweets in this case. What you need to do is to make sure that your mapJavaObjects() method returns a Tweets object with the tweets loaded by ObjectMapper and after this is done your code should look like this:
tweets = wtp.mapJavaObject();
Something like this:
public Tweets mapJavaObject() {
String jsonFile = twitterFile.getName();
Tweets ret = null;
System.out.println("Mapping JSON to WeatherTweet Class.");
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
try {
ret = (Tweets) mapper.readValue(new File(jsonFile), Tweets.class);
} catch (JsonParseException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Finished Mapping of JSON File.");
retrun ret;
}
{
"status": "Success",
"message": "Contents retrieved successfully",
"name": {
"1": "God",
"2": "Goat"
},
"sites": {
"1": "google",
"2": "yahoo",
"3": "bing"
},
"places": [
"UK",
"AU",
"US"
],
"images": {
"1": {
"1x": "http://3.bp.blogspot.com/-PPrUA_pcNyI/Udtx6v7MlvI/AAAAAAAADZA/6X2Qu-FcHtA/s320/Android+JSON+stream+data+parsing+example+using+Gson.png",
"2x": "http://3.bp.blogspot.com/-PPrUA_pcNyI/Udtx6v7MlvI/AAAAAAAADZA/6X2Qu-FcHtA/s320/Android+JSON+stream+data+parsing+example+using+Gson.png"
},
"2": {
"1x": "http://3.bp.blogspot.com/-PPrUA_pcNyI/Udtx6v7MlvI/AAAAAAAADZA/6X2Qu-FcHtA/s320/Android+JSON+stream+data+parsing+example+using+Gson.png",
"2x": "http://3.bp.blogspot.com/-PPrUA_pcNyI/Udtx6v7MlvI/AAAAAAAADZA/6X2Qu-FcHtA/s320/Android+JSON+stream+data+parsing+example+using+Gson.png"
},
"3": {
"1x": "http://3.bp.blogspot.com/-PPrUA_pcNyI/Udtx6v7MlvI/AAAAAAAADZA/6X2Qu-FcHtA/s320/Android+JSON+stream+data+parsing+example+using+Gson.png",
"2x": "http://3.bp.blogspot.com/-PPrUA_pcNyI/Udtx6v7MlvI/AAAAAAAADZA/6X2Qu-FcHtA/s320/Android+JSON+stream+data+parsing+example+using+Gson.png"
}
}
}
My Class
import java.util.Map;
public class Data {
String status;
String message;
Map<String, String> name;
Map<String, String> Sites;
#Override
public String toString() {
return "Data [status=" + status + ", message=" + message
+ ", name=" + name + ", Sites=" + Sites
+ "]";
}
}
this class returns null value for the while retrieving sites and names
name and sites are JSONObjects no Arrays. Any Object in a JSON have to deserialised in a class using GSON.
So try this,
public class MyJson {
String status;
String message;
Sites sites;
List<String> places;
}
public class Sites {
String 1;
String 2;
String 3;
}
and so on for every Object. For Arrays you can use List / Map.
To use it make a call like this:
Gson gson = new Gson();
MyJson myJson = gson.fromJson(yourJsonString, MyJson.class);
JsonParser parser = new JsonParser();
JsonObject object = (JsonObject)parser.parse(yourString);
for (Map.Entry<String,JsonElement> entry : object.entrySet()) {
JsonArray array = entry.getValue().getAsJsonArray();
for (JsonElement elementJSON : array) {
[...]
}
}