Вы можете использовать библиотеки Jackson для привязки JSON String к экземплярам POJO ( Обычный объект Java ). POJO - это просто класс с только частными полями и общедоступными методами getter / setter. Джексон собирается пересечь методы (используя отражение) и отображает объект JSON в экземпляр POJO, поскольку имена полей класса соответствуют именам полей объекта JSON.
В вашем объекте JSON, который на самом деле является составным объектом, основной объект состоит из двух под-объектов. Итак, наши классы POJO должны иметь одинаковую иерархию. Я назову весь объект JSON как объект страницы. Объект страницы состоит из объекта PageInfo и массива объектов Post.
Итак, мы должны создать три разных класса POJO:
Единственным пакетом, который я использовал, является Jackson ObjectMapper, то, что мы делаем, является обязательными данными ;
com.fasterxml.jackson.databind.ObjectMapper
Необходимые зависимости, файлы jar перечислены ниже:
Вот требуемый код:
package com.levo.jsonex.model;
public class Page {
private PageInfo pageInfo;
private Post[] posts;
public PageInfo getPageInfo() {
return pageInfo;
}
public void setPageInfo(PageInfo pageInfo) {
this.pageInfo = pageInfo;
}
public Post[] getPosts() {
return posts;
}
public void setPosts(Post[] posts) {
this.posts = posts;
}
}
package com.levo.jsonex.model;
public class PageInfo {
private String pageName;
private String pagePic;
public String getPageName() {
return pageName;
}
public void setPageName(String pageName) {
this.pageName = pageName;
}
public String getPagePic() {
return pagePic;
}
public void setPagePic(String pagePic) {
this.pagePic = pagePic;
}
}
package com.levo.jsonex.model;
public class Post {
private String post_id;
private String actor_id;
private String picOfPersonWhoPosted;
private String nameOfPersonWhoPosted;
private String message;
private int likesCount;
private String[] comments;
private int timeOfPost;
public String getPost_id() {
return post_id;
}
public void setPost_id(String post_id) {
this.post_id = post_id;
}
public String getActor_id() {
return actor_id;
}
public void setActor_id(String actor_id) {
this.actor_id = actor_id;
}
public String getPicOfPersonWhoPosted() {
return picOfPersonWhoPosted;
}
public void setPicOfPersonWhoPosted(String picOfPersonWhoPosted) {
this.picOfPersonWhoPosted = picOfPersonWhoPosted;
}
public String getNameOfPersonWhoPosted() {
return nameOfPersonWhoPosted;
}
public void setNameOfPersonWhoPosted(String nameOfPersonWhoPosted) {
this.nameOfPersonWhoPosted = nameOfPersonWhoPosted;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public int getLikesCount() {
return likesCount;
}
public void setLikesCount(int likesCount) {
this.likesCount = likesCount;
}
public String[] getComments() {
return comments;
}
public void setComments(String[] comments) {
this.comments = comments;
}
public int getTimeOfPost() {
return timeOfPost;
}
public void setTimeOfPost(int timeOfPost) {
this.timeOfPost = timeOfPost;
}
}
Я только что скопировал ваш образец JSON в этот файл и поместил его в папку проекта.
{
"pageInfo": {
"pageName": "abc",
"pagePic": "http://example.com/content.jpg"
},
"posts": [
{
"post_id": "123456789012_123456789012",
"actor_id": "1234567890",
"picOfPersonWhoPosted": "http://example.com/photo.jpg",
"nameOfPersonWhoPosted": "Jane Doe",
"message": "Sounds cool. Can't wait to see it!",
"likesCount": "2",
"comments": [],
"timeOfPost": "1234567890"
}
]
}
package com.levo.jsonex;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.levo.jsonex.model.Page;
import com.levo.jsonex.model.PageInfo;
import com.levo.jsonex.model.Post;
public class JSONDemo {
public static void main(String[] args) {
ObjectMapper objectMapper = new ObjectMapper();
try {
Page page = objectMapper.readValue(new File("sampleJSONFile.json"), Page.class);
printParsedObject(page);
} catch (IOException e) {
e.printStackTrace();
}
}
private static void printParsedObject(Page page) {
printPageInfo(page.getPageInfo());
System.out.println();
printPosts(page.getPosts());
}
private static void printPageInfo(PageInfo pageInfo) {
System.out.println("Page Info;");
System.out.println("**********");
System.out.println("\tPage Name : " + pageInfo.getPageName());
System.out.println("\tPage Pic : " + pageInfo.getPagePic());
}
private static void printPosts(Post[] posts) {
System.out.println("Page Posts;");
System.out.println("**********");
for(Post post : posts) {
printPost(post);
}
}
private static void printPost(Post post) {
System.out.println("\tPost Id : " + post.getPost_id());
System.out.println("\tActor Id : " + post.getActor_id());
System.out.println("\tPic Of Person Who Posted : " + post.getPicOfPersonWhoPosted());
System.out.println("\tName Of Person Who Posted : " + post.getNameOfPersonWhoPosted());
System.out.println("\tMessage : " + post.getMessage());
System.out.println("\tLikes Count : " + post.getLikesCount());
System.out.println("\tComments : " + Arrays.toString(post.getComments()));
System.out.println("\tTime Of Post : " + post.getTimeOfPost());
}
}
Page Info;
****(*****
Page Name : abc
Page Pic : http://example.com/content.jpg
Page Posts;
**********
Post Id : 123456789012_123456789012
Actor Id : 1234567890
Pic Of Person Who Posted : http://example.com/photo.jpg
Name Of Person Who Posted : Jane Doe
Message : Sounds cool. Can't wait to see it!
Likes Count : 2
Comments : []
Time Of Post : 1234567890
Что может случиться, так это то, что SignalData косвенно меняет словарь подписчиков под капотом во время цикла и приводит к этому сообщению. Вы можете проверить это, изменив
foreach(Subscriber s in subscribers.Values)
To
foreach(Subscriber s in subscribers.Values.ToList())
Если я прав, проблема исчезнет
Примечание. В целом коллекции .Net не поддерживают перечисление и изменение в одно и то же время. Если вы попытаетесь изменить список коллекции, пока находитесь в середине перечисления, это вызовет исключение.
Таким образом, проблема этой ошибки заключается в том, что мы не можем изменять список / словарь во время цикла через. Но если мы итерируем словарь, используя временный список его ключей, мы можем изменить словарь, потому что теперь мы не итерируем словарь (и итерируем его коллекцию ключей).
sample:
//get key collection from dictionary into a list to loop through
List<int> keys = new List<int>(Dictionary.Keys);
// iterating key collection using simple for-each loop
foreach (int key in keys)
{
// Now we can perform any modification with values of dictionary.
Dictionary[key] = Dictionary[key] - 1;
}
Вот сообщение в блоге об этом решении.
И для глубокого погружения в stackoverflow: Почему эта ошибка возникает? ]
Таким образом, другой способ решить эту проблему был бы вместо того, чтобы удалять элементы, создающие новый словарь, и добавлять только те элементы, которые вы не хотели удалить, а затем заменить исходный словарь на новый. Я не думаю, что это слишком большая проблема эффективности, потому что она не увеличивает количество раз, когда вы перебираете структуру.
На самом деле проблема заключается в том, что вы удаляете элементы из списка и ожидаете продолжить чтение списка, как будто ничего не случилось.
Что вам действительно нужно сделать, так это начать с конца и обратно к началу. Даже если вы удалите элементы из списка, вы сможете продолжить чтение.
Хорошо, так что помогло мне повторить назад. Я пытался удалить запись из списка, но итерации вверх, и это закрутило цикл, потому что запись больше не существовала:
for (int x = myList.Count - 1; x > -1; x--)
{
myList.RemoveAt(x);
}
Я видел много вариантов для этого, но для меня этот был лучшим.
ListItemCollection collection = new ListItemCollection();
foreach (ListItem item in ListBox1.Items)
{
if (item.Selected)
collection.Add(item);
}
Затем просто прокрутите коллекцию.
Имейте в виду, что ListItemCollection может содержать дубликаты. По умолчанию в сборнике ничего не мешает дублированию. Чтобы избежать дублирования, вы можете сделать это:
ListItemCollection collection = new ListItemCollection();
foreach (ListItem item in ListBox1.Items)
{
if (item.Selected && !collection.Contains(item))
collection.Add(item);
}
Когда абонент отказывается от подписки, вы меняете содержимое коллекции подписчиков во время перечисления.
Существует несколько способов исправить это, один из которых меняет цикл for, чтобы использовать явный .ToList()
:
public void NotifySubscribers(DataRecord sr)
{
foreach(Subscriber s in subscribers.Values.ToList())
{
^^^^^^^^^
...
Вы также можете заблокировать словарь подписчиков, чтобы он не изменялся всякий раз, когда он был зациклен:
lock (subscribers)
{
foreach (var subscriber in subscribers)
{
//do something
}
}
InvalidOperationException - произошло событие InvalidOperationException. Он сообщает, что «коллекция была изменена» в foreach-loop
Использовать оператор break, После удаления объекта.
ex:
ArrayList list = new ArrayList();
foreach (var item in list)
{
if(condition)
{
list.remove(item);
break;
}
}
У меня была такая же проблема, и она была решена, когда я использовал цикл for
вместо foreach
.
// foreach (var item in itemsToBeLast)
for (int i = 0; i < itemsToBeLast.Count; i++)
{
var matchingItem = itemsToBeLast.FirstOrDefault(item => item.Detach);
if (matchingItem != null)
{
itemsToBeLast.Remove(matchingItem);
continue;
}
allItems.Add(itemsToBeLast[i]);// (attachDetachItem);
}
Вы можете скопировать объект словаря подписчиков на объект временного словаря того же типа, а затем перебрать временный объект словаря с помощью цикла foreach.
Более эффективным способом, на мой взгляд, является наличие другого списка, в котором вы заявляете, что вы помещаете все, что нужно «удалить». Затем, после завершения основного цикла (без .ToList ()), вы делаете еще один цикл над списком «для удаления», удаляя каждую запись, когда это происходит. Итак, в своем классе вы добавляете:
private List<Guid> toBeRemoved = new List<Guid>();
Затем вы меняете его на:
public void NotifySubscribers(DataRecord sr)
{
toBeRemoved.Clear();
...your unchanged code skipped...
foreach ( Guid clientId in toBeRemoved )
{
try
{
subscribers.Remove(clientId);
}
catch(Exception e)
{
System.Diagnostics.Debug.WriteLine("Unsubscribe Error " +
e.Message);
}
}
}
...your unchanged code skipped...
public void UnsubscribeEvent(Guid clientId)
{
toBeRemoved.Add( clientId );
}
Это не только решит вашу проблему, это не позволит вам продолжать создавать список из вашего словаря, который стоит дорого, если там много подписчиков. Предполагая, что список абонентов, которые будут удалены на любой заданной итерации, будет меньше, чем общее число в списке, это должно быть быстрее. Но, конечно, не стесняйтесь профилировать его, чтобы быть уверенным, что это так, если есть какие-либо сомнения в вашей конкретной ситуации использования.