【问题标题】:Parsing Nested JSon File in Xamarin Forms在 Xamarin 表单中解析嵌套的 JSon 文件
【发布时间】:2019-07-16 15:03:25
【问题描述】:

我正在使用 Xamarin 开发跨平台应用程序。数据源是一个 JSON 文件,其中包含一些单词及其押韵,如下所示。我必须从 JSON 文件中读取单词,为此我设计了一个模型类“WordRhyme.cs”。 。我的代码运行良好,但由于某些原因,我无法检索每个单词的押韵。过去三天我一直在努力寻找解决方案,但没有运气。当 Rhymes 返回一个列表时,我还尝试用嵌套在单词列表中的列表替换标签,但这不起作用(xaml 编码在下面添加)。还有一种方法可以只从 JSON 中选择几条记录,因为它可能有数百条记录,但我想显示一些。在谷歌搜索学习之前,我还没有在 Xamarin 中编程过。

json1.json

{
  "words": [

    {
      "word": "coffee",
      "syllables": 2,
      "topic": "Food and drink",
      "rhymes": [
        {
          "word": "toffee",
          "score": 385,
          "numSyllables": 2
        },
        {
          "word": "naafi",
          "score": 178,
          "numSyllables": 2
        },
        {
          "word": "tophi",
          "score": 172,
          "numSyllables": 2
        },
        {
          "word": "sofie",
          "score": 75,
          "numSyllables": 2
        },
          {
          "word": "yoffie",
          "numSyllables": 2
        }
      ]
    },

    {
      "word": "Cat",
      "syllables": 2,
      "topic": "Animals",
      "rhymes": [
        {
          "word": "Hat",
          "score": 385,
          "numSyllables": 2
        },
        {
          "word": "Fat",
          "score": 178,
          "numSyllables": 2
        },
        {
          "word": "Mat",
          "score": 172,
          "numSyllables": 2
        },
        {
          "word": "coffey2",
          "score": 152,
          "numSyllables": 2
        },
        {
          "word": "toffy2",
          "score": 119,
          "numSyllables": 2
        }      ]
    }
  ]
}

WordRhyme.cs

using System;
using System.Collections.Generic;
using System.Text;

namespace JsonTest2.Models
{

    public class Rhyme
    {
        public string word { get; set; }
        public int score { get; set; }
        public int numSyllables { get; set; }
    }

    public class Word
    {
        public string word { get; set; }
        public int syllables { get; set; }
        public string topic { get; set; }
        public List<Rhyme> rhymes { get; set; }
    }

    public class WordRhymes
    {
        public List<Word> words { get; set; }
    }
}

Page1.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             x:Class="JsonTest2.Page1">
    <ContentPage.Content>
        <StackLayout Orientation="Vertical">
            <Grid>
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="*"/>
                        <RowDefinition Height="*"/>
                    </Grid.RowDefinitions>
                    <Label Grid.Row="0" Margin="30" Text="Rhyming Words JSON Parsing" FontSize="25" />
                    <ListView x:Name="listViewWords" Grid.Row="1" HorizontalOptions="FillAndExpand" Footer="" HasUnevenRows="True">
                        <ListView.ItemTemplate>
                            <DataTemplate>
                                <ViewCell>
                                    <Grid HorizontalOptions="FillAndExpand" Padding="10">
                                        <Grid.RowDefinitions>
                                            <RowDefinition Height="Auto"/>
                                            <RowDefinition Height="Auto"/>
                                            <RowDefinition Height="Auto"/>
                                            <RowDefinition Height="Auto"/>
                                            <RowDefinition Height="Auto"/>
                                            <RowDefinition Height="Auto"/>
                                            <RowDefinition Height="Auto"/>
                                        </Grid.RowDefinitions>
                                        <Label Text="{Binding word}" HorizontalOptions="StartAndExpand" Grid.Row="0" TextColor="Blue"  FontAttributes="Bold"/>
                                        <Label Text="{Binding syllables}" HorizontalOptions="StartAndExpand" Grid.Row="1" TextColor="Orange"  FontAttributes="Bold"/>
                                        <Label Text="{Binding topic}" HorizontalOptions="StartAndExpand" Grid.Row="2" TextColor="Gray"  FontAttributes="Bold"/>
                                        <Label Text="{Binding rhymes.word}" Grid.Row="3" TextColor="Blue"  FontAttributes="Bold"/>
                                        <Label Text="{Binding rhymes.score}" Grid.Row="4" TextColor="Blue"  FontAttributes="Bold"/>
                                        <Label Text="{Binding rhymes.numSyllables}" Grid.Row="5" TextColor="Blue"  FontAttributes="Bold"/>
                                        <BoxView HeightRequest="2" Margin="0,10,10,0" BackgroundColor="Gray" Grid.Row="6" HorizontalOptions="FillAndExpand" />
                                    </Grid>
                                </ViewCell>
                            </DataTemplate>
                        </ListView.ItemTemplate>
                    </ListView>
                </Grid>
            </Grid>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

Page1.xaml.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Reflection;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using JsonTest2.Models;
using Newtonsoft.Json;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace JsonTest2
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class Page1 : ContentPage
    {
        public Page1()
        {
            InitializeComponent();
            GetJsonData();
        }

        void GetJsonData()
        {
            string jsonFileName = "json1.json";
            WordRhymes ObjWordList = new WordRhymes();
            var assembly = typeof(Page1).GetTypeInfo().Assembly;
            Stream stream = assembly.GetManifestResourceStream($"{assembly.GetName().Name}.{jsonFileName}");
            using (var reader = new System.IO.StreamReader(stream))
            {
                var jsonString = reader.ReadToEnd();

                //Converting JSON Array Objects into generic list  
                ObjWordList = JsonConvert.DeserializeObject<WordRhymes>(jsonString);
            }
            //Binding listview with json string   
            listViewWords.ItemsSource = ObjWordList.words;
        }
    }
}

嵌套 ListView Page2Json.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             x:Class="JsonTest2.Page2Json">
    <ContentPage.Content>
        <StackLayout Orientation="Vertical">
            <Grid>
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="*"/>
                        <RowDefinition Height="*"/>
                    </Grid.RowDefinitions>
                    <Label Grid.Row="0" Margin="30" Text="Rhyming Words JSON Parsing" FontSize="25" />
                    <ListView x:Name="listViewWords" Grid.Row="1" HorizontalOptions="FillAndExpand" Footer="" HasUnevenRows="True">
                        <ListView.ItemTemplate>
                            <DataTemplate>
                                <ViewCell>
                                    <Grid HorizontalOptions="FillAndExpand" Padding="10">
                                        <Grid.RowDefinitions>
                                            <RowDefinition Height="Auto"/>
                                            <RowDefinition Height="Auto"/>
                                            <RowDefinition Height="Auto"/>
                                            <RowDefinition Height="Auto"/>
                                            <RowDefinition Height="Auto"/>
                                        </Grid.RowDefinitions>
                                        <Label Text="{Binding word}" HorizontalOptions="StartAndExpand" Grid.Row="0" TextColor="Blue"  FontAttributes="Bold"/>
                                        <Label Text="{Binding syllables}" HorizontalOptions="StartAndExpand" Grid.Row="1" TextColor="Orange"  FontAttributes="Bold"/>
                                        <Label Text="{Binding topic}" HorizontalOptions="StartAndExpand" Grid.Row="2" TextColor="Gray"  FontAttributes="Bold"/>
                                        <ListView x:Name="listViewRhymes" HorizontalOptions="FillAndExpand" ItemsSource="{Binding listViewWords.rhymes}">
                                            <ListView.ItemTemplate>
                                                <DataTemplate>
                                                    <ViewCell>
                                                        <Grid HorizontalOptions="FillAndExpand">
                                                            <Grid.RowDefinitions>
                                                                <RowDefinition Height="Auto"/>
                                                                <RowDefinition Height="Auto"/>
                                                                <RowDefinition Height="Auto"/>
                                                            </Grid.RowDefinitions>
                                                            <Label Text="{Binding rhymes.word}"></Label>
                                                            <Label Text="{Binding rhymes.score}"></Label>
                                                            <Label Text="{Binding rhymes.numSyllables}"></Label>
                                                        </Grid>
                                                    </ViewCell>
                                                </DataTemplate>
                                            </ListView.ItemTemplate>

                                        </ListView>
                                        <Label Text="{Binding rhymes.word}" HorizontalOptions="StartAndExpand" Grid.Row="2" TextColor="Gray"  FontAttributes="Bold"/>
                                        <BoxView HeightRequest="2" Margin="0,10,10,0" BackgroundColor="Gray" Grid.Row="3" HorizontalOptions="FillAndExpand" />
                                    </Grid>
                                </ViewCell>
                            </DataTemplate>
                        </ListView.ItemTemplate>
                    </ListView>
                    <StackLayout Orientation="Horizontal">
                        <Button x:Name="nextButton" Text="Next" Clicked="NextButton_Clicked"></Button>
                        <Button x:Name="backButton" Text="Back" Clicked="BackButton_Clicked"></Button>
                    </StackLayout>
                </Grid>
            </Grid>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

【问题讨论】:

  • 是解析 json(与 Xamarin 无关)还是显示它的问题?你需要先缩小范围。此外,嵌套 ListView 是一个可怕的想法。最后,您的外部 StackLayout 和 Grid 似乎真的没有任何用途。
  • @Jason 你能解释一下为什么解析 JSON 文件有问题吗?我设计的类具有正确数据类型的所有字段/属性。我猜 WordRhymes 和 Word 类被正确解析,因为它们能够检索数据。是的,我知道使用嵌套的 ListViews 不是一个好主意,但为了让我的代码正常工作,我已经尝试过了。
  • 我没说是。我在问你。您的问题标题明确表示“解析嵌套的 json”,但问题的主体暗示 UI 存在问题。这是两个完全不同的东西。你需要弄清楚哪个是真正的问题。确定您的 json 是否正确反序列化到您的模型中应该是相当简单的。
  • @Jason,我认为这可能是两者都有问题,这就是我发布所有代码的原因。我会再次检查,谢谢您的帮助。
  • @Aisha 嗨,如果回答有帮助,记得标记它:)

标签: json xamarin


【解决方案1】:

因此,在 Page2Json.xaml 的内部列表中,您的 itemsource 与 listViewWords.rhymes 绑定,我认为应该只是 rhymes,即使在此列表视图中,标签也不应该与 rhymes.something 绑定,而应该是 something 这是我认为应该可以工作的更新代码

<ListView x:Name="listViewRhymes" ItemsSource="{Binding rhymes}" HorizontalOptions="FillAndExpand">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <Grid HorizontalOptions="FillAndExpand">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="Auto" />
                    </Grid.RowDefinitions>
                    <Label Text="{Binding word}" />
                    <Label Text="{Binding score}" />
                    <Label Text="{Binding numSyllables}" />
                </Grid>
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

这些更改是考虑到您的 page2json.xaml.cs 与 page1json.xaml.cs 相同

【讨论】:

  • 我会试一试,但请您检查一下 WordRhyme.cs 文件并判断它是否设计正确?
  • 为什么不自己验证数据呢?使用调试器检查 ObjWordList 并验证它是否包含您期望的数据。
  • @Aisha 你的类在我看来很好,但正如 Jason 所说,你可以很容易地使用调试器来验证。
  • 我现在正在做。谢谢
  • JSON 文件被正确解析,我想通了,所以现在问题出在 UI 上。绑定嵌套 JSON 的首选控件是什么?如果我使用嵌套列表视图,它只显示第一条记录。
猜你喜欢
  • 1970-01-01
  • 2020-08-29
  • 1970-01-01
  • 1970-01-01
  • 2020-12-14
  • 1970-01-01
  • 1970-01-01
  • 2020-05-21
  • 2021-07-27
相关资源
最近更新 更多